كيف يمكنني تعطيل الاستيفاء المتغير باستخدام عامل استبدال Perl؟

StackOverflow https://stackoverflow.com//questions/12678519

  •  12-12-2019
  •  | 
  •  

سؤال

أحاول استبدال سطر معين في ملف نصي على 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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top