ابحث عن نص واستبدله داخل ملف باستخدام الأوامر

كيف يمكنني العثور على واستبدال كلمات معينة في ملف نصي باستخدام سطر الأوامر?

sed -i 's/original/new/g' file.txt

الشرح:

  • sed = محرر تيار
  • -i = في المكان (أي حفظ مرة أخرى إلى الملف الأصلي)
  • سلسلة الأوامر:

    • s = الأمر البديل
    • original = تعبير عادي يصف الكلمة المراد استبدالها (أو الكلمة نفسها فقط)
    • new = النص ليحل محله مع
    • g = عالمي (أي استبدال الكل وليس فقط التكرار الأول)
  • file.txt = اسم الملف

هناك العديد من الطرق لتحقيق ذلك. اعتمادا على مدى تعقيد ما يحاول المرء تحقيقه باستبدال السلسلة ، واعتمادا على الأدوات التي يكون المستخدم مألوفا بها ، قد يتم تفضيل بعض الطرق أكثر من غيرها.

في هذه الإجابة أنا باستخدام بسيطة input.txt ملف ، والتي يمكنك استخدامها لاختبار جميع الأمثلة المقدمة هنا. محتويات الملف:

roses are red , violets are blueThis is an input.txt and this doesn't rhyme

باش

باش ليس المقصود حقا لمعالجة النصوص، ولكن يمكن أن يتم بدائل بسيطة عن طريق توسيع المعلمة ، على وجه الخصوص هنا يمكننا استخدام بنية بسيطة ${parameter/old_string/new_string}.

#!/bin/bashwhile IFS= read -r linedo    case "$line" in       *blue*) printf "%s\n" "${line/blue/azure}" ;;       *) printf "%s\n" "$line" ;;    esacdone < input.txt

لا يقوم هذا البرنامج النصي الصغير باستبدال موضعي ، مما يعني أنه سيتعين عليك حفظ نص جديد في ملف جديد ، والتخلص من الملف القديم ، أو mv new.txt old.txt

ملاحظة جانبية: إذا كنت مهتما بالسبب while IFS= read -r ; do ... done < input.txt يستخدم ، انها في الأساس طريقة قذيفة لقراءة خط الملف عن طريق الخط. انظر هذا كمرجع.

أوك

أوك ، كونه أداة معالجة النصوص ، هو مناسب تماما لهذه المهمة. يمكن أن تفعل بدائل بسيطة وأخرى أكثر تقدما على أساس التعبيرات العادية. يوفر وظيفتين: sub() و gsub(). أول واحد يستبدل فقط حدوث الأول فقط ، في حين أن الثاني-يستبدل الحوادث في سلسلة كاملة. على سبيل المثال ، إذا كان لدينا سلسلة one potato two potato ، ستكون هذه النتيجة:

$ echo "one potato two potato" | awk '{gsub(/potato/,"banana")}1'one banana two banana$ echo "one potato two potato" | awk '{sub(/potato/,"banana")}1'                                      one banana two potato 

أوك يمكن أن تأخذ ملف الإدخال كوسيطة، لذلك تفعل نفس الأشياء مع input.txt ، سيكون من السهل:

awk '{sub(/blue/,"azure")}1' input.txt

اعتمادا على إصدار أوك لديك ، قد أو قد لا يكون التحرير في مكان ، وبالتالي فإن الممارسة المعتادة هي حفظ واستبدال النص الجديد. على سبيل المثال شيء من هذا القبيل:

awk '{sub(/blue/,"azure")}1' input.txt > temp.txt && mv temp.txt input.txt

سيد

سيد هو محرر خط. كما أنه يستخدم التعبيرات العادية ، ولكن بالنسبة للبدائل البسيطة ، يكفي القيام بذلك:

sed 's/blue/azure/' input.txt

ما هو جيد حول هذه الأداة هو أن لديها التحرير في المكان ، والتي يمكنك تمكين مع -i علم.

بيرل

بيرل هو أداة أخرى والتي غالبا ما تستخدم لمعالجة النصوص ، ولكنها لغة للأغراض العامة ، ويستخدم في الشبكات ، وإدارة النظام ، وتطبيقات سطح المكتب ، والعديد من الأماكن الأخرى. اقترضت الكثير من المفاهيم/الميزات من لغات أخرى مثل ج ، سيد ، أوك ، وغيرها. يمكن إجراء استبدال بسيط على النحو التالي:

perl -pe 's/blue/azure/' input.txt

مثل سيد ، بيرل أيضا العلم ط.

بايثون

هذه اللغة متعددة الاستخدامات وتستخدم أيضا في مجموعة متنوعة من التطبيقات. لديها الكثير من الوظائف للعمل مع السلاسل، من بينها replace()، لذلك إذا كان لديك متغير مثل var="Hello World" ، يمكنك القيام به var.replace("Hello","Good Morning")

طريقة بسيطة لقراءة الملف واستبدال سلسلة في ذلك سيكون على النحو التالي:

python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt

مع بيثون ، ومع ذلك ، تحتاج أيضا إلى الإخراج إلى ملف جديد ، والتي يمكنك أيضا القيام به من داخل البرنامج النصي نفسه. على سبيل المثال ، هنا واحد بسيط:

#!/usr/bin/env pythonimport sysimport osimport tempfiletmp=tempfile.mkstemp()with open(sys.argv[1]) as fd1, open(tmp[1],'w') as fd2:    for line in fd1:        line = line.replace('blue','azure')        fd2.write(line)os.rename(tmp[1],sys.argv[1])

هذا السيناريو هو أن يسمى مع input.txt كوسيطة سطر الأوامر. الأمر الدقيق لتشغيل البرنامج النصي بيثون مع وسيطة سطر الأوامر سيكون

 $ ./myscript.py input.txt

أو

$ python ./myscript.py input.txt

بالطبع ، تأكد من ذلك ./myscript.py هو في دليل العمل الحالي الخاص بك وللطريقة الأولى ، تأكد من تعيين قابل للتنفيذ مع chmod +x ./myscript.py

بيثون يمكن أن يكون أيضا التعبيرات العادية ، على وجه الخصوص، هناك re الوحدة ، التي لديها re.sub() وظيفة ، والتي يمكن استخدامها لاستبدال أكثر تقدما.

هناك عدد من الطرق المختلفة للقيام بذلك. واحد يستخدم sed والتعبير العادي. سيد هو محرر تيار لتصفية وتحويل النص. مثال واحد هو كما يلي:

marco@imacs-suck: ~$ echo "The slow brown unicorn jumped over the hyper sleeping dog" > orlymarco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarlymarco@imacs-suck: ~$ cat yarlyThe quick brown unicorn jumped over the hyper sleeping dog

طريقة أخرى قد تكون أكثر منطقية من < strin و > strout هو مع الأنابيب!

marco@imacs-suck: ~$ cat yarly | sed s/unicorn/fox/ | sed s/hyper/lazy/ > nowaimarco@imacs-suck: ~$ cat nowai The quick brown fox jumped over the lazy sleeping dog

من خلال قيادة غسوب أوك,

awk '{gsub(/pattern/,"replacement")}' file

مثال:

awk '{gsub(/1/,"0");}' file

في المثال أعلاه ، يتم استبدال جميع 1 من قبل 0 بغض النظر عن العمود حيث يقع.


إذا كنت تريد أن تفعل بديل على عمود معين، ثم تفعل مثل هذا,

awk '{gsub(/pattern/,"replacement",column_number)}' file

مثال:

awk '{gsub(/1/,"0",$1);}' file

يستبدل 1 بـ 0 في العمود الأول فقط.

من خلال بيرل,

$ echo 'foo' | perl -pe 's/foo/bar/g'bar