كيف يمكنني تعطيل الاستيفاء المتغير باستخدام عامل استبدال Perl؟
سؤال
أحاول استبدال سطر معين في ملف نصي على VMS.عادة، هذا عبارة عن سطر واحد بسيط مع لغة Perl.لكنني واجهت مشكلة عندما كان الجانب البديل عبارة عن رمز يحتوي على مسار VMS.هذا هو الملف وما جربته:
محتويات file1.txt:
foo
bar
baz
quux
محاولة استبدال السطر الثالث:
$ mysub = "disk$data1:[path.to]file.txt"
$ perl -pe "s/baz/''mysub'/" file1.txt
يعطي الإخراج التالي:
foo
bar
disk:[path.to]file.txt
quux
يبدو أن بيرل كان متحمسًا جدًا واستبدل $data1
جزء من المسار يحتوي على محتويات متغير غير موجود (أي لا شيء).أكد التشغيل مع المصحح ذلك.أنا لم العرض /e
, ، لذلك اعتقدت أن بيرل يجب أن يستبدل النص كما هو.هل هناك طريقة لجعل بيرل يفعل ذلك؟
(لاحظ أيضًا أنه يمكنني إعادة إنتاج سلوك مماثل في سطر أوامر Linux.)
المحلول
من خلال المزيج الصحيح من علامات الاقتباس وعلامات الاقتباس المزدوجة، يمكنك الوصول إلى هناك:
نقوم بإنشاء سلسلة ضيقة من "سلسلة" + "رمز بديل" + "سلسلة".تحتوي السلسلتان المقتبستان المزدوجتان على علامات اقتباس مفردة للبديل.متفق...لكنها تعمل.
$ perl -pe "s'baz'"'mysub'"'" file1.txt
هذا هو الحل على مستوى DCL.
للحصول على حل بيرل، استخدم q()
عامل تشغيل لسلسلة غير محرفة وتنفيذ ذلك.أدخل الرمز داخل الأقواس باستخدام استبدال DCL البسيط.هذا هو المفضل لدي لأنه (تقريبًا) منطقي بالنسبة لي ولا يربكني كثيرًا مع الاقتباسات.
$ perl -pe "s/baz/q(''mysub')/e" file1.txt
نصائح أخرى
مثل رواخ اكتشفت عند قراءة تعليقي أن مشكلة استيفاء لغة Perl يمكن حلها عن طريق الوصول إلى ملف %ENV
التجزئة، بدلاً من استخدام متغير الصدفة:
perl -pwe "s/baz/$ENV{mysub}/" file1.txt
تمت الإضافة -w
لأنني لا أؤمن بعدم الاستخدام warnings
حتى في الخطوط الواحدة.
لم أشاهد حتى نظام VMS منذ عقود، ولكن...الهروب من سيجيل الخاص بك؟
$ mysub = "disk\$data1:[path.to]file.txt"
أو ربما
$ mysub = "disk\\$data1:[path.to]file.txt"
?
ل sh
أو مشتق، سأستخدمه
perl -pe'BEGIN { $r = shift(@ARGV) } s/baz/$r/' "$mysub" file1.txt
خلاف ذلك، عليك أن تخفي قيمة بطريقة أو بأخرى mysub
في سلسلة بيرل الحرفية.سيكون ذلك أكثر تعقيدًا.ابحث عن المعادل لقذيفة الخاص بك.
تحرير بواسطة OP:
نعم، هذا يعمل.ما يعادل VMS هو
perl -pe "BEGIN { $r = shift(@ARGV) } s/baz/$r/" 'mysub' file1.txt
عليك الهروب من $
مع \$
.وإلا فإن بيرل يرى مرجعًا متغيرًا ويستبدل السلسلة $data1
مع محتوى $data1
قبل تقييم التعبير العادي.كما لم تحدد $data1
إنه فارغ بالطبع.
يمكنك استخدام الكود التالي :
$ mysub='disk\$data1:[path.to]file.txt'
$ perl -pe 's/baz/'$mysub'/' FILE
foo
bar
disk$data1:[path.to]file.txt
quux
يمكنك تجربة استخدام اسم منطقي بدلاً من رمز DCL:
$ define mysub "disk$data1:[path.to]file.txt"
$ $ perl -pe "s/baz/mysub/" file1.txt
استخدم سيد.
سيد لن يحاول الاستيفاء $data1
كمتغير، لذلك يجب أن تحصل على ما تريد.
$ sed -e "s/baz/''mysub'/" file1.txt