উদ্দীপনা চিহ্ন `!` মাঝে মাঝে খারাপ করে কেন?


14

আমি বুঝতে পারি যে !কমান্ডলাইন ইতিহাসের প্রেক্ষাপটে কমান্ডলাইনে বিশেষ তাত্পর্য রয়েছে তবে এগুলি বাদ দিয়ে চলমান স্ক্রিপ্টে বিস্মরণ চিহ্নটি মাঝে মাঝে বিশ্লেষণ ত্রুটির কারণ হতে পারে।
আমি মনে করি এটির সাথে কিছু করার eventআছে তবে কোনও ইভেন্ট কী বা এটি কী করে তা আমার কোনও ধারণা নেই। তবুও, একই কমান্ড বিভিন্ন পরিস্থিতিতে ভিন্ন আচরণ করতে পারে।
নীচের সর্বশেষ উদাহরণটি একটি ত্রুটির কারণ; কিন্তু কেন, যখন একই কোডটি কমান্ড প্রতিস্থাপনের বাইরে কাজ করেছিল? GNU ব্যাশ ব্যবহার করে 4.1.5

# This works, with or without a space between ! and p
  { echo -e "foo\nbar" | sed -nre '/foo/! p'
    echo -e "foo\nbar" | sed -nre '/foo/!p'; }
# bar
# bar

# This works, works when there is a space between ! and p
  var="$(echo -e "foo\nbar" | sed -nre '/foo/! p')"; echo "$var"
# bar

# This causes an ERROR, with NO space between ! and p
  var="$(echo -e "foo\nbar" | sed -nre '/foo/!p')"; echo "$var"
# bash: !p': event not found


@ ওয়ারেন .. ধন্যবাদ আমি দেখেছি যে কিউএ, তবে এটি কেবল ব্যাকস্ল্যাশ থেকে কীভাবে বাঁচতে হবে তা নিয়েই কথা বলে ... আমার সমস্যাটি আরও জড়িত যে আপাতদৃষ্টিতে ইতিমধ্যে পালানো কোডটি অন্য পরিস্থিতিতে নয় কেন একটি পরিস্থিতিতে কাজ করে ...
পিটার.ও

@ ফ্রেড: "আপাতদৃষ্টিতে ইতিমধ্যে পালিয়ে গেছে"? আমি কোনও পালাতে দেখছি না এবং আপনি ডাবল উদ্ধৃতি ব্যবহার করছেন। আমার (সংশোধিত) উত্তর দেখুন। আপনি কি ভাবেন যে পালিয়ে গেছে?
কালেব

@Caleb। হ্যাঁ, আমি ভুল শব্দটি ব্যবহার করেছি .. protectedআরও উপযুক্ত হত। ('একক উদ্ধৃতি' দ্বারা সুরক্ষিত)
পিটার.ও

আপনি যদি কেবল সাধারণ কার্যনির্বাহী সম্পর্কে উদ্বিগ্ন হন তবে আপনি ব্যবহার করতে পারেন var=$(…)(ডাবল কোট নেই) এবং এটি আপনার প্রত্যাশার মতো কাজ করবে (আমার মনে হয়)। এখনও "নিরাপদ" কারণ একটি সহজ নিয়োগ মান অংশ শব্দ বিভাজন সাপেক্ষে বা globbing (যদিও এই যেমন builtins মাধ্যমে (বরাদ্দকরণ এর সত্য নাও হতে পারে নয় export, localইত্যাদি সব শাঁস অধীনে))। দুর্ভাগ্যক্রমে, এটি সাধারণ কার্যভারের বাইরে প্রসারিত হয় না, কারণ ডাবল উক্তি হ'ল শব্দ বিভাজন এবং গ্লোব্বিংয়ের হাত থেকে রক্ষা করার উপায়, অন্য প্রসঙ্গে অন্য প্রকারের প্রসারণের পরেও।
ক্রিস জনসন

উত্তর:


12

!চরিত্র ব্যাশ ইতিহাসে প্রতিকল্পন ডাকে। যখন কোনও স্ট্রিং অনুসরণ করা হয় (যেমন আপনার ব্যর্থতার উদাহরণ হিসাবে) এটি সেই স্ট্রিং দিয়ে শুরু হওয়া সর্বশেষ ইতিহাসের ইভেন্টে প্রসারিত করার চেষ্টা করে। ঠিক $varসেই স্ট্রিংয়ের মান বাড়ানো যেমন !echoআপনার ইতিহাসের শেষ প্রতিধ্বনি কমান্ডে প্রসারিত হবে।

স্থান বিস্তৃতিতে একটি বিরতিপূর্ণ চরিত্র। ভেরিয়েবলগুলির সাথে এটি কীভাবে কাজ করবে তা প্রথম দ্রষ্টব্য:

# var="like"
# echo "$var"
like
# echo "$"
$
# echo "Do you $var frogs?"
Do you like frogs?       <- as expected, variable name broken at space
# echo "Do you $varfrogs?"
Do you?                  <- $varfrogs not defined, replaced with blank
# echo "Do you $ var frogs?"
Do you $ var frogs?      <- $ not a valid variable name, ignored

ইতিহাস বিস্তারের ক্ষেত্রেও একই ঘটনা ঘটবে। ঠাট্টা অক্ষর ( !) ইতিহাস প্রতিস্থাপনের ক্রমটি শুরু করে তবে কেবল স্ট্রিংয়ের পরে। একটি স্থানের সাথে এটি অনুসরণ করে এটি প্রতিস্থাপনের ক্রমের অংশের পরিবর্তে আক্ষরিক ঠাঁই করে তোলে।

আপনি একক উদ্ধৃতি ব্যবহার করে পরিবর্তনশীল এবং ইতিহাস বিস্তারের উভয়ের জন্য এই জাতীয় প্রতিস্থাপন এড়াতে পারেন। আপনার প্রথম উদাহরণগুলিতে একক উদ্ধৃতি ব্যবহৃত হয়েছে এবং তাই দুর্দান্ত ছিল। আপনার শেষ উদাহরণগুলি ডাবল উক্তিগুলিতে রয়েছে এবং এর ফলে এটি অন্য কিছু করার আগে ব্যাশ সেগুলিকে বিস্তৃত ক্রমের জন্য স্ক্যান করে। প্রথমটি ট্রিপ না করার একমাত্র কারণটি হল উপরে বর্ণিত স্থানটি একটি বিরতি চরিত্র।


ধন্যবাদ কালেব .. আমার আরেকটি পূর্ব ধারণাটি খারিজ করা হয়েছে ... আমি ভেবেছিলাম যে ব্যাশ পার্সিংটি আন্তঃতম বন্ধনী বা ব্রেস থেকে করা হয়েছিল, এবং তারপরে বাহিরের বাইরে কাজ করেছিল ... মনে হয় বাশ আমার অনুমানের থেকে আলাদাভাবে পার্স করেছে।
পিটার.ও

1
নেস্টিং স্ট্রিংগুলিতে পরিবর্তন না করেই উদ্ধৃতিটি যথেষ্ট পরিমাণে বিভ্রান্ত করছে। যেমনটি হয়, প্রতিস্থাপনগুলি প্রক্রিয়াটির খুব শীঘ্রই ঘটে। এই উদাহরণটি বিবেচনা করুন:var=word; echo "test '$var'"; echo 'test "$var"'
কালেব

.. হ্যাঁ আনস্টুড। আমি উদ্ধৃতিগুলিতে বাসা বাঁধার বিষয়ে সচেতন ছিলাম ... আমার ভুল ধারণাটি হ'ল আমি ভেবেছিলাম যে কমান্ড প্রতিস্থাপনের বন্ধনীগুলির মধ্যে কোডটি those বন্ধনীগুলির চারপাশে কি আলাদাভাবে বিভক্ত হবে; কিন্তু আপাতদৃষ্টিতে না .. ধন্যবাদ।
পিটার.ও

6

যেমনটি কালেব ইতিমধ্যে বলেছেন , !বাশের ইতিহাস প্রতিস্থাপনের জন্য ব্যবহৃত হয়।

আমার মতো যদি আপনার মনে হয় আপনার এমন বৈশিষ্ট্যের দরকার নেই তবে আপনি নীচের লাইনটি এতে প্রবেশ করে এটি অক্ষম করতে পারেন ~/.bashrc:

set +H

আমি এটা প্রয়োজন হবে না কারণ ইতিহাস তীর দ্বারা উদ্ধার করা সম্ভব না Ctrl- rক্রমবর্ধমান বিপরীত অনুসন্ধান। শর্টকাটের বিশদ তালিকার জন্য বাশের ম্যানুয়াল পৃষ্ঠা, বিভাগটি ইতিহাসের হেরফেরের জন্য বিভাগ কমান্ডগুলি দেখুন


2
তুমি কীভাবে বাঁচবে !!?
কালেব

। ধন্যবাদ, আমি যে, কোন সমস্যা বহনযোগ্যতা ভিত্তিক হতে পারে মনে হবে, কিন্তু ব্যবহার set +Hলিপিতে ঠিক যেমন ভাল কাজ করে :) + 1
Peter.O

2
@ ফ্রেড: অদ্ভুত, সাধারণত ইতিহাসের বিস্তার কেবলমাত্র ইন্টারেক্টিভ শেলের জন্য "চালু" থাকে is
এনজোটিব

@ এঞ্জো .. আবারও ধন্যবাদ .. আমি কমান্ডলাইন থেকে এটি পরীক্ষা করেছিলাম .. আহ! শেখার এত মজা না হলে ক্লান্তি লাগত ... আমি কি কফির কথা উল্লেখ করেছি? এটি খুব সাহায্য করে :)
পিটার.ও

ইয়া, এটা একটা গ্যাচা। আমি স্ক্রিপ্টগুলি থেকে আটকানো কোডটি অনুলিপি করেছি যা কেবল এই কারণে কমান্ড লাইনে ব্যর্থ হয়েছিল। ইতিহাসের প্রসারণ স্ক্রিপ্টে উদ্বেগের বিষয় ছিল না তবে এটি একটি ইন্টারেক্টিভ শেলের উপর রয়েছে।
কালেব

2

আপনার প্রথম উদাহরণ:

{ echo -e "foo\nbar" | sed -nre '/foo/! p'
    echo -e "foo\nbar" | sed -nre '/foo/!p'; }

কমে যেতে পারে

echo '! p' 
echo '!p'

একক উদ্ধৃতিতে সমস্ত অক্ষর তাদের আক্ষরিক মান সংরক্ষণ করে। এইভাবে !এর বিশেষ অর্থটি হারিয়ে গেছে এবং ইতিহাসের প্রসারণটি পূর্ববর্তী নয়।

আপনার দ্বিতীয় এবং তৃতীয় উদাহরণ:

var="$(echo -e "foo\nbar" | sed -nre '/foo/! p')"; echo "$var"

var="$(echo -e "foo\nbar" | sed -nre '/foo/!p')"; echo "$var"

কমে যেতে পারে

echo "'! p'"

echo "'!p'"

'! p'এবং '!p'মূলত ডাবল উদ্ধৃত স্ট্রিংগুলির অংশ।

উদ্ধৃতি চিহ্ন মধ্যে, সমস্ত অক্ষর তাদের আক্ষরিক মান সংরক্ষণ ছাড়া $ , `, \এবং !

এটি এর একক উদ্ধৃতি বোঝায় '! p'এবং '!p'তাদের বিশেষ অর্থ হারিয়ে ফেলেছে (অর্থাত: পালাতে অক্ষম !) তবে !এর বিশেষ অর্থ ধরে রেখেছে এভাবে ইতিহাসের সম্প্রসারণ সম্পাদিত হয়।

যাইহোক, যখন !কোনও স্থানের অক্ষর অনুসরণ করা হয়, ইতিহাসের সম্প্রসারণ সম্পাদিত হয় না।

থেকে উদ্ধৃতি man bash:

মূল্য উদ্ধৃতি

[...]

একক উদ্ধৃতিতে অক্ষরগুলি বদ্ধ করা প্রতিটি উদ্ধৃতিগুলির মধ্যে আক্ষরিক মান সংরক্ষণ করে। [...]

Double, `, \, এবং, যখন ইতিহাসের প্রসারণ সক্ষম করা হয়, ব্যতীত ডাবল উদ্ধৃতিগুলিতে অক্ষরগুলি আবদ্ধ করাতে উদ্ধৃতিগুলির মধ্যে সমস্ত অক্ষরের আক্ষরিক মান সংরক্ষণ করা হয়! [...] সক্ষম করা থাকলে ইতিহাসের সম্প্রসারণ সম্পাদনা করা হবে যদি না! ডাবল উদ্ধৃতিতে উপস্থিত হওয়া ব্যাকস্ল্যাশ ব্যবহার করে পালিয়ে যায়। এর আগের দিকের ব্যাকস্ল্যাশ! অপসারণ করা হয় না।

Pতিহাসিক বিবরণ

[...]

ইতিহাস বিস্তারের পরিচয় দিয়ে ইতিহাসের সম্প্রসারণ চরিত্রের উপস্থিতি ঘটে, যা! গতানুগতিক. কেবল ব্যাকস্ল্যাশ (\) এবং একক উদ্ধৃতিই ইতিহাসের সম্প্রসারণের চরিত্রটি উদ্ধৃত করতে পারে।

ইতিহাসের সম্প্রসারণের চরিত্রটি অবিলম্বে পাওয়া গেলে বেশিরভাগ অক্ষর ইতিহাসের প্রসারকে বাধা দেয়, এমনকি যদি তা অব্যক্ত না হয়: স্থান, ট্যাব, নিউলাইন, ক্যারেজ রিটার্ন এবং =। যদি এক্সট্লোব শেল বিকল্পটি সক্ষম করা থাকে, (এছাড়াও সম্প্রসারণকে বাধা দেয়)।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.