كيفية الهروب طويلة أنماط التوسع مسار في التعبيرات نقلت؟
-
22-08-2019 - |
سؤال
وبالإضافة إلى أنماط *
، ?
و[...]
الأساسية، يوفر باش قذيفة نمط الموسعة مطابقة مشغلي مثل !(pattern-list)
( "تتطابق مع كل ما عدا واحدة من أنماط معينة"). يحتاج الخيار extglob
قذيفة لتعيين استخدامها. مثال:
~$ mkdir test ; cd test ; touch file1 file2 file3
~/test$ echo *
file1 file2 file3
~/test$ shopt -s extglob # make sure extglob is set
~/test$ echo !(file2)
file1 file3
إذا مررت على التعبير قذيفة على البرنامج الذي ينفذ في قذيفة الفرعية، المشغل يسبب خطأ. وهنا الاختبار الذي يدير قذيفة الفرعية مباشرة (هنا أنا المنفذة من دليل آخر لجعل التوسع يقين لا يحدث قبل الأوان):
~/test$ cd ..
~$ bash -c "cd test ; echo *"
file1 file2 file3
~$ bash -c "cd test ; echo !(file2)" # expected output: file1 file3
bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `cd test ; echo !(file2)'
ولقد جربت كل أنواع الهروب، ولكن عملت شيء جئت مع صحيح. أنا أيضا لم يتم تعيين يشتبه extglob
في قذيفة الفرعية، ولكن هذا ليس هو الحال:
~$ bash -c "shopt -s extglob ; cd test ; echo !(file2)"
bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `cd test ; echo !(file2)'
وأي حل تقدير!
المحلول
$ bash -O extglob -c 'echo !(file2)' file1 file3
نصائح أخرى
وباش يوزع كل سطر قبل تنفيذ المشروع، وذلك "shopt -s extglob" لن اتخذت المفعول عند باش التحقق من صحة بناء الجملة نمط globbing. الخيار لا يمكن تمكين على نفس الخط. هذا هو السبب في حل "باش -O extglob -c" س ع ص "(من راندي بروكتر) يعمل ومطلوب.
إليك طريقة أخرى، إذا كنت ترغب في تجنب eval
وتحتاج إلى أن تكون قادرة على تحويل extglob م> وخارجها ضمن المستوى الفرعي. وضعت للتو أسلوبك في متغير:
bash -c 'shopt -s extglob; cd test; patt="!(file2)"; echo $patt; shopt -u extglob; echo $patt'
ويعطي هذا الناتج:
file1 file3
!(file2)
وكان من المقرر أن التظاهر <م> extglob م> وضبطه. إذا كان echo
أول علامات الاقتباس حول $patt
، فإنه يبصق فقط من نمط مثل echo
الثانية (التي ربما ينبغي أن يكون الاقتباس).
حسنا، ليس لدي أي خبرتها حقيقية مع extglob م>، ولكن يمكنني الحصول على عمل من خلال التفاف echo
في eval
:
$ bash -c 'shopt -s extglob ; cd test ; eval "echo !(file2)"'
file1 file3