bash - كيفية القيام بعثر/استبدال تتابع لسلسلة مع awk من sed؟




replace (20)

كيف يمكنني العثور على كل حدث واستبداله:

subdomainA.example.com

مع

subdomainB.example.com

في كل ملف نصي تحت شجرة /home/www/ directory (العودية / الاستبدال)؟


أبسط طريقة بالنسبة لي هي

grep -rl oldtext . | xargs sed -i 's/oldtext/newtext/g'

إذا كان النص الخاص بك يتضمن الحرف / المسار ، فيمكنك استبداله بحرف محدد آخر مثل:

grep -rl 'oldtext/' . | xargs sed -i 's|oldtext/|newtext/|g'

أنا فقط استخدم قمم:

find . -name '*.[c|cc|cp|cpp|m|mm|h]' -print0 |  xargs -0 tops -verbose  replace "verify_noerr(<b args>)" with "__Verify_noErr(<args>)" \
replace "check(<b args>)" with "__Check(<args>)" 

إذا كان لديك إمكانية الوصول إلى عقدة ، فيمكنك إجراء npm install -g rexreplace ثم

rexreplace 'subdomainA.example.com' 'subdomainB.example.com' /home/www/**/*.*

إذا كنت ترغب في استخدام هذا بدون تدمير مخزن SVN بالكامل ، فيمكنك إخبار 'find' لتجاهل جميع الملفات المخفية عن طريق العمل:

find . \( ! -regex '.*/\..*' \) -type f -print0 | xargs -0 sed -i 's/subdomainA.example.com/subdomainB.example.com/g'

باستخدام مزيج من grep و sed

for pp in $(grep -Rl looking_for_string)
do
    sed -i 's/looking_for_string/something_other/g' "${pp}"
done

بالنسبة لـ Qshell (qsh) في IBMi ، لا bash كما هو موضح بواسطة OP.

قيود أوامر qsh:

  • ليس لدى الخيار -print0
  • xargs ليس لديها الخيار -0
  • السيد ليس لديه الخيار -i

وبالتالي الحل في qsh:

    PATH='your/path/here'
    SEARCH=\'subdomainA.example.com\'
    REPLACE=\'subdomainB.example.com\'

    for file in $( find ${PATH} -P -type f ); do

            TEMP_FILE=${file}.${RANDOM}.temp_file

            if [ ! -e ${TEMP_FILE} ]; then
                    touch -C 819 ${TEMP_FILE}

                    sed -e 's/'$SEARCH'/'$REPLACE'/g' \
                    < ${file} > ${TEMP_FILE}

                    mv ${TEMP_FILE} ${file}
            fi
    done

المحاذير:

  • يستثني الحل معالجة الأخطاء
  • لا Bash كما هو موضح بواسطة OP

جرب هذا:

sed -i 's/subdomainA/subdomainB/g' `grep -ril 'subdomainA' *`

فقط لتجنب التغيير أيضا

  • NearlysubdomainA.example.com
  • subdomainA.example.comp.other

لكن مازال

  • subdomainA.example.com.IsIt.good

(ربما ليست جيدة في الفكرة وراء جذر المجال)

find /home/www/ -type f -exec sed -i 's/\bsubdomainA\.example\.com\b/\1subdomainB.example.com\2/g' {} \;

لأي شخص يستخدم الباحث الفضي ( ag )

ag SearchString -l0 | xargs -0 sed -i 's/SearchString/Replacement/g'

بما أن ag يتجاهل ملفات git / hg / svn بشكل افتراضي ، فهذا آمن للتشغيل داخل مستودع التخزين.


لاستبدال كل التكرارات في مستودع git ، يمكنك استخدام:

git ls-files -z | xargs -0 sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g'

انظر قائمة الملفات في المحلية git repo؟ للخيارات الأخرى لسرد جميع الملفات في مستودع. تخبرك خيارات -z git بفصل أسماء الملفات مع البايت صفر ، مما يضمن أن xargs (مع الخيار -0 ) يمكن أن يفصل أسماء الملفات ، حتى إذا كانت تحتوي على مسافات أو غيرها.


لتقليص الملفات sed المتكرر ، يمكنك استخدام grep لمثيل السلسلة:

grep -rl <oldstring> /path/to/folder | xargs sed -i s^<oldstring>^<newstring>^g

إذا قمت بتشغيل man grep فسوف تلاحظ أنه يمكنك أيضًا تحديد علامة --exlude-dir="*.git" إذا كنت تريد حذف البحث من خلال الدلائل .git ، وتجنب مشكلات مؤشر git كما أشار آخرون بأدب.

تقودك إلى:

grep -rl --exclude-dir="*.git" <oldstring> /path/to/folder | xargs sed -i s^<oldstring>^<newstring>^g

هذا هو الحل الأفضل الذي وجدته لـ OSX و Windows (msys2). يجب أن تعمل مع أي شيء يمكن أن تحصل على نسخة جنو من sed. يتخطى الدلائل .git حتى لا يفسد اختبارك.

على الماك ، فقط قم بتثبيت النواة أولاً وتأكد من أن gsed في المسار -

brew install coreutils

ثم أضع هذه الوظيفة في zshrc / bashrc ->

replace-recursive() {
    hash gsed 2>/dev/null && local SED_CMD="gsed" || SED_CMD="sed"
    find . -type f -name "*.*" -not -path "*/.git/*" -print0 | xargs -0 $SED_CMD -i "s/$1/$2/g"
}

usage: replace-recursive <find> <replace>

واحد oneliner واحد لطيف. باستخدام git grep.

git grep -lz 'subdomainA.example.com' | xargs -0 perl -i'' -pE "s/subdomainA.example.com/subdomainB.example.com/g"

وفقًا لمقالة المدونة this :

find . -type f | xargs perl -pi -e 's/oldtext/newtext/g;'

يمكنك استخدام awk لحل هذا على النحو التالي ،

for file in `find /home/www -type f`
do
   awk '{gsub(/subdomainA.example.com/,"subdomainB.example.com"); print $0;}' $file > ./tempFile && mv ./tempFile $file;
done

ارجوا ان يساعدك هذا !!!


grep -lr 'subdomainA.example.com' | while read file; do sed -i "s/subdomainA.example.com/subdomainB.example.com/g" "$file"; done

أعتقد أن معظم الناس لا يعرفون أنهم يستطيعون توجيه شيء ما إلى "أثناء قراءة الملف" وأنه يتفادى تلك الحواجز السيئة -print0 ، بينما يحافظ على المسافات في أسماء الملفات.

إضافة المزيد من echo قبل الإسطوانة يسمح لك بمشاهدة الملفات التي سوف تتغير قبل القيام بذلك بالفعل.


ملاحظة : لا تقم بتشغيل هذا الأمر في مجلد بما في ذلك git repo - قد تؤدي التغييرات في .git إلى تلف مؤشر git الخاص بك.

find /home/www -type f -print0 | xargs -0 sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g'

من man find :

-print0 (العثور على GNU فقط) يخبرنا بالعثور على استخدام الحرف الفارغ (\ 0) بدلاً من whitespace كمحدد المخرجات بين أسماء المسار التي تم العثور عليها. هذا خيار أكثر أمانًا إذا كان يمكن أن تحتوي الملفات على فراغات أو أحرف خاصة أخرى. من المستحسن استخدام الوسيطة -print0 للعثور على ما إذا كنت تستخدم أمر -exec أو xargs (يلزم وجود الوسيطة -0 في xargs.).


ملاحظة : لا تقم بتشغيل هذا الأمر في مجلد بما في ذلك git repo - قد تؤدي التغييرات في .git إلى تلف مؤشر git الخاص بك.

find /home/www/ -type f -exec \
    sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +

مقارنة مع إجابات أخرى هنا ، وهذا هو أبسط من معظم ويستخدم ليرة لبنانية بدلا من بيرل ، وهو ما طرح السؤال الأصلي.


cd /home/www && find . -type f -print0 |
  xargs -0 perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g'

find /home/www/ -type f -exec perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +

find /home/www/ -type f قائمة بجميع الملفات في / home / www / (والدلائل الفرعية). يخبر العلم "-exec" العثور على تشغيل الأمر التالي على كل ملف العثور عليه.

perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +

هو الأمر الذي يعمل على الملفات (الكثير في كل مرة). يتم استبدال {} بأسماء الملفات. يخبر + في نهاية الأمر عن إنشاء أمر واحد للعديد من أسماء الملفات.

في صفحة find رجل: "تم بناء سطر الأوامر بالطريقة نفسها التي يبني بها xargs خطوط الأوامر الخاصة به."

وبالتالي من الممكن تحقيق هدفك (والتعامل مع أسماء الملفات التي تحتوي على مسافات) دون استخدام xargs -0 أو -print0 .





replace