Bagaimana cara mencari / mengganti string dengan awk atau sed secara rekursif?


678

Bagaimana cara menemukan dan mengganti setiap kemunculan:

subdomainA.example.com

dengan

subdomainB.example.com

di setiap file teks di bawah /home/www/pohon direktori secara rekursif?


93
Kiat: Jangan lakukan yang di bawah ini di pohon checkout svn ... itu akan menimpa file folder ajaib .svn.
J. Polfer 8-10

7
Ya Tuhan, inilah yang baru saja saya lakukan. Tapi itu berhasil dan sepertinya tidak ada salahnya. Apa hal terburuk yang bisa terjadi?
J. Katzwinkel

5
@ J.Katzwinkel: paling tidak, itu dapat merusak checksum, yang dapat merusak repositori Anda.
ninjagecko

3
Kiat cepat untuk semua orang yang menggunakan sed: Ini akan menambahkan trailing baris baru ke file Anda. Jika Anda tidak menginginkannya, pertama-tama lakukan pencarian-ganti yang tidak cocok dengan apa pun, dan lakukan itu untuk git. Kemudian lakukan yang asli. Kemudian rebase secara interaktif dan hapus yang pertama.
funroll

5
Anda dapat mengecualikan direktori, seperti git, dari hasil dengan menggunakan -path ./.git -prune -odi find . -path ./.git -prune -o -type f -name '*matchThisText*' -print0sebelum pipa ke xargs
devinbost

Jawaban:


851
find /home/www \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g'

-print0memberitahu finduntuk mencetak setiap hasil yang dipisahkan oleh karakter nol, daripada baris baru. Jika direktori Anda memiliki file dengan baris baru di namanya, ini masih memungkinkan xargsbekerja pada nama file yang benar.

\( -type d -name .git -prune \)adalah ekspresi yang sepenuhnya melompati semua direktori yang bernama .git. Anda dapat dengan mudah mengembangkannya, jika Anda menggunakan SVN atau memiliki folder lain yang ingin Anda pertahankan - cukup cocokkan dengan lebih banyak nama. Ini kira-kira setara dengan -not -path .git, tetapi lebih efisien, karena daripada memeriksa setiap file dalam direktori, itu melompati seluruhnya. The -osetelah itu diperlukan karena cara -prunebenar-benar bekerja.

Untuk informasi lebih lanjut, lihat man find.


132
Pada OSX Anda mungkin mengalami sed: 1: "...": invalid command code .masalah. Tampaknya opsi -i mengharapkan ekstensi dan mem-parsing 's/../...'perintah keluar. Solusi: berikan ekstensi '' ke -i opsi seperti sed -i '' 's/....
Robert Lujo

6
Catatan: jika Anda menggunakan ini di direktori dan bertanya-tanya mengapa svn sttidak menunjukkan perubahan, itu karena Anda telah memodifikasi file di direktori .svn juga! Gunakan find . -maxdepth 1 -type f -print0 | xargs -0 sed -i 's/toreplace/replaced/g'sebagai gantinya.
ACK_stoverflow

57
Juga, berhati-hatilah jika Anda berada di git repo. Saya pikir saya pintar dengan menguji ini pada cabang yang jelas sehingga saya bisa kembali jika melakukan sesuatu yang buruk, tetapi malah merusak indeks git saya.
Ciryon

13
Gunakan ini grep -r 'hello' -l --null . | xargs -0 sed -i 's#hello#world#g'untuk menghindari mengedit file yang tidak terkait (sed mungkin mengubah pengkodean file).
caiguanhao

6
"Tapi malah merusak indeks git saya." Jangan terlalu khawatir tentang hal ini yang bisa Anda lakukan find .git ... | ... 'sed -i s/(the opposite from before)/g'untuk memperbaiki indeks git Anda
Massey101

259

Catatan : Jangan jalankan perintah ini pada folder termasuk git repo - perubahan ke. Git dapat merusak indeks git Anda.

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

Dibandingkan dengan jawaban lain di sini, ini lebih sederhana daripada kebanyakan dan menggunakan sed bukan perl, yang merupakan pertanyaan awal.


50
Perhatikan bahwa jika Anda menggunakan BSD sed (termasuk di Mac OS X) Anda harus memberikan string kosong secara eksplisit ke -iopsi sed . yaitu: sed -i '' 's/original/replacement/g'
Nathan Craike

2
@JohnZwinck Kesalahan saya, melewatkan +. Anehnya, solusi Nikita berjalan lebih cepat untuk saya.
Sam

6
@ AoeAoe: Sangat +mengurangi jumlah sedproses yang dihasilkan. Ini lebih efisien.
John Zwinck

4
Bagaimana saya bisa melakukan ini dengan aman di folder dengan git repo?
Hatshepsut

20
Ini aman untuk mengeksekusi pada folder yang berisi repo git jika Anda mengecualikan repo dari hasil find Anda: find . -not -path '*/\.git*' -type f ....
Dale Anderson

211

Cara paling sederhana bagi saya adalah

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

1
@Anatoly: hanya satu pertanyaan: bagaimana saya bisa mengecualikan file biner (file executable) ?
user2284570

3
@ user2284570 Gunakan -Iatau --binary-file=without-matchgrep flag.
Zéychin

34
Ini bekerja sangat baik, ketika Anda perlu mengecualikan direktori, suka dengan .svn. Misalnya:grep -rl oldtext . --exclude-dir=.svn | xargs sed -i 's/oldtext/newtext/g'
phyatt

11
brew install gnu-seddan gunakan gsedpada OSX untuk menghindari dunia kesakitan.
P i

1
orang-orang menyenangkan perhatian, jika proyek Anda git berversi, gunakan ini sebagai gantinya: git grep -rl oldtext . | xargs sed -i 's/oldtext/newtext/g'. itu tidak baik sama sekali untuk mendapatkan .gitdir Anda
Paolo

61

Semua triknya hampir sama, tapi saya suka yang ini:

find <mydir> -type f -exec sed -i 's/<string1>/<string2>/g' {} +
  • find <mydir>: lihat di direktori.

  • -type f:

    File bertipe: file biasa

  • -exec command {} +:

    Varian aksi -exec ini menjalankan perintah yang ditentukan pada file yang dipilih, tetapi baris perintah dibangun dengan menambahkan setiap nama file yang dipilih di akhir; jumlah total doa perintah akan jauh lebih sedikit daripada jumlah file yang cocok. Baris perintah dibangun dengan cara yang sama seperti xargs membangun baris perintahnya. Hanya satu instance dari `{} 'diizinkan dalam perintah. Perintah dijalankan di direktori awal.


@ user2284570 dengan -exec? Cobalah untuk mengatur path ke executable daripada nama alat.
1515

@ I159: Tidak: kecualikan binari yang dapat dieksekusi (tetapi sertakan skrip shell) .
user2284570

8
@ I159 Bukankah jawaban ini identik dengan John Zwinck ?
Reinstate Monica Please

1
@ user2284570 Konsep "file biner" tidak sepenuhnya didefinisikan dengan baik. Anda dapat menggunakan fileperintah untuk mencoba menentukan jenis file masing-masing, tetapi variasi serampangan dalam outputnya mungkin sedikit membingungkan. Opsi -I(alias --mime) agak membantu, atau --mime-typejika Anda memilikinya. Bagaimana tepatnya untuk memperbaiki ini satu-liner rapi untuk melakukan ini sayangnya di luar jangkauan untuk kotak komentar kecil ini. Mungkin memposting pertanyaan terpisah jika Anda butuh bantuan? (Mungkin tambahkan komentar dengan tautan di sini.)
tripleee

1
jawaban paling bersih! terima kasih sobat
jukerok

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

2
Saya ingin tahu, apakah ada alasan untuk menggunakan -print0dan xargsbukannya -execatau -execdir?
Philipp

4
Ada: dari "man find": Perintah yang ditentukan dijalankan sekali untuk setiap file yang cocok. Yaitu, jika ada 2000 file di / home / www, maka 'find ... -exec ...' akan menghasilkan 2000 doa perl; sedangkan 'temukan ... | xargs ... 'hanya akan memanggil perl sekali atau dua kali (dengan asumsi ARG_MAX sekitar 32K dan panjang rata-rata nama file 20).
Dipekerjakan Rusia

2
@ Dipekerjakan Rusia: itu sebabnya Anda akan menggunakan find -exec command {} +- itu memang menghindari pemanggilan perintah yang berlebihan seperti xargs, tetapi tanpa proses terpisah.
John Zwinck

2
Di platform mana? Solusi xargs adalah portable, doa "ajaib" dari "find ... -exec" yang tidak memanggil subproses untuk setiap file yang ditemukan bukan.
Dipekerjakan Rusia

4
@EmployedRussian, find -exec ... {} +telah ditentukan POSIX sejak 2006.
Charles Duffy

34

Bagi saya solusi termudah untuk diingat adalah https://stackoverflow.com/a/2113224/565525 , yaitu:

sed -i '' -e 's/subdomainA/subdomainB/g' $(find /home/www/ -type f)

CATATAN : -i ''memecahkan masalah OSXsed: 1: "...": invalid command code .

CATATAN : Jika ada terlalu banyak file untuk diproses, Anda akan mendapatkannya Argument list too long. Solusi - penggunaan find -execatau xargssolusi yang dijelaskan di atas.


4
The workaroundharus sintaks yang lebih disukai dalam semua kasus.
Reinstate Monica Please

1
Masalah dengan substitusi perintah $(find...)adalah bahwa tidak ada cara bagi shell untuk menangani nama file dengan spasi putih atau karakter meta shell lainnya di dalamnya. Jika Anda tahu ini bukan masalah, pendekatan ini baik-baik saja; tetapi kami memiliki terlalu banyak pertanyaan di mana orang tidak diberi peringatan tentang masalah ini, atau tidak memahami peringatan itu.
tripleee

30

Bagi siapa pun yang menggunakan pencari perak ( ag)

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

Karena ag mengabaikan file / folder git / hg / svn secara default, ini aman untuk dijalankan di dalam repositori.


16

Satu oneliner yang bagus sebagai tambahan. Menggunakan git grep.

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

3
Ide bagus jika bekerja di dalam git repo karena Anda tidak mengambil risiko menimpa .git / konten (seperti yang dilaporkan dalam komentar untuk jawaban lain).
mahemoff

1
Terima kasih, saya menggunakannya sebagai bash function refactor() { echo "Replacing $1 by $2 in all files in this git repository." git grep -lz $1| xargs -0 perl -i'' -pE "s/$1/$2/g" }Usage, misalnya untuk mengganti 'kata' dengan 'pedang': refactor word swordlalu verifikasi dengan apa itu git diff.
Paul Rougieux

16

Untuk mengurangi file secara rekursif sed, Anda bisa grepmenggunakan string misalnya:

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

Jika Anda menjalankan, man grepAnda akan melihat bahwa Anda juga dapat menentukan --exlude-dir="*.git"bendera jika Anda ingin menghilangkan pencarian melalui direktori .git, menghindari masalah indeks git seperti yang orang lain tunjukkan dengan sopan.

Menuntun Anda ke:

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

13

Yang ini kompatibel dengan repositori git, dan sedikit lebih sederhana:

Linux:

git grep -l 'original_text' | xargs sed -i 's/original_text/new_text/g'

Mac:

git grep -l 'original_text' | xargs sed -i '' -e 's/original_text/new_text/g'

(Terima kasih kepada http://blog.jasonmeridth.com/posts/use-git-grep-to-replace-strings-in-files-in-your-git-repository/ )


Bijaksana untuk menggunakan git-grep's -zpilihan bersama dengan xargs -0.
gniourf_gniourf

git grepjelas hanya masuk akal dalam gitrepo. Pengganti umum akan menjadi grep -r.
tripleee

@gniourf_gniourf Bisakah Anda jelaskan?
Petr Peller

2
@PetrPeller: with -z, git-grepakan memisahkan bidang output dengan null byte, bukan baris baru; dan dengan -0, xargsakan membaca input yang dipisahkan oleh byte nol, bukannya kosong (dan tidak melakukan hal-hal aneh dengan tanda kutip). Jadi jika Anda tidak ingin perintah untuk istirahat jika nama file mengandung spasi, tanda kutip atau karakter lucu lainnya, perintahnya adalah: git grep -z -l 'original_text' | xargs -0 sed ....
gniourf_gniourf

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

find /home/www/ -type f akan mencantumkan semua file di / home / www / (dan subdirektori-nya). Bendera "-exec" memberi tahu find untuk menjalankan perintah berikut pada setiap file yang ditemukan.

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

adalah perintah yang dijalankan pada file (banyak sekaligus). The {}akan digantikan oleh nama file. Di +akhir perintah memberitahu finduntuk membangun satu perintah untuk banyak nama file.

Per findhalaman manual: "Baris perintah dibangun dengan cara yang sama seperti xargs membangun baris perintahnya."

Dengan demikian dimungkinkan untuk mencapai tujuan Anda (dan menangani nama file yang mengandung spasi) tanpa menggunakan xargs -0, atau -print0.


8

Saya hanya membutuhkan ini dan tidak senang dengan kecepatan contoh yang tersedia. Jadi saya membuat sendiri:

cd /var/www && ack-grep -l --print0 subdomainA.example.com | xargs -0 perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g'

Ack-grep sangat efisien dalam menemukan file yang relevan. Perintah ini menggantikan ~ 145.000 file dengan mudah, sedangkan yang lain memakan waktu sangat lama sehingga saya tidak bisa menunggu sampai selesai.


Bagus, tetapi grep -ril 'subdomainA' *tidak ada yang dekat secepat grep -Hr 'subdomainA' * | cut -d: -f1.
trusktr

@ Halo: hanya satu pertanyaan: bagaimana saya bisa mengecualikan file biner (file yang dapat dieksekusi) ?
user2284570

ack-grep melakukan itu secara otomatis untuk Anda.
Henno

@ Henno: Apakah ini termasuk skrip shell?
user2284570

Iya. Berikut adalah daftar lengkap jenis file mendukung: beyondgrep.com/documentation
Henno

6

Metode langsung jika Anda perlu mengecualikan direktori ( --exclude-dir=.svn) dan juga mungkin memiliki nama file dengan spasi (menggunakan 0Byte dengan grep -Zdanxargs -0

grep -rlZ oldtext . --exclude-dir=.svn | xargs -0 sed -i 's/oldtext/newtext/g'

6

Cara termudah untuk mengganti ( semua file, direktori, rekursif )

find . -type f -not -path '*/\.*' -exec sed -i 's/foo/bar/g' {} +

Catatan: Terkadang Anda mungkin perlu mengabaikan beberapa file tersembunyi yaitu .git, Anda dapat menggunakan perintah di atas.

Jika Anda ingin menyertakan file tersembunyi gunakan,

find . -type f  -exec sed -i 's/foo/bar/g' {} +

Dalam kedua kasus string fooakan diganti dengan string barubar


5

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

Saya kira sebagian besar orang tidak tahu bahwa mereka dapat menyalurkan sesuatu ke dalam file "sambil membaca" dan itu menghindari argumen -print0 jahat, sementara ruang presevering dalam nama file.

Lebih lanjut menambahkan echosebelum sed memungkinkan Anda untuk melihat file apa yang akan berubah sebelum benar-benar melakukannya.


Alasannya -print0berguna adalah bahwa ia menangani kasus-kasus yang while readtidak bisa ditangani - baris baru adalah karakter yang valid dalam nama file Unix, jadi agar kode Anda benar-benar kuat, perlu juga menangani nama file seperti itu. (Juga, Anda ingin read -rmenghindari beberapa perilaku warisan POSIX yang sial di read.)
tripleee

Juga, sedini adalah no-op jika tidak ada kecocokan, jadi grepitu tidak benar-benar diperlukan; meskipun ini adalah pengoptimalan yang berguna untuk menghindari menulis ulang file yang tidak mengandung kecocokan, jika Anda memiliki banyak, atau ingin menghindari memperbarui cap tanggal pada file yang tidak perlu.
tripleee

5

Anda dapat menggunakan awk untuk menyelesaikan ini seperti di bawah ini,

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

harap ini akan membantu Anda !!!


Bekerja pada MacO tanpa masalah! Semua sedperintah berbasis gagal ketika binari dimasukkan bahkan dengan pengaturan spesifik osx.
Jankapunkt

Hati-hati ... ini akan meledak jika ada file yang findkembali memiliki ruang dalam nama mereka! Ini jauh lebih aman untuk digunakan while read: stackoverflow.com/a/9612560/1938956
Soren Bjornstad

4

Coba ini:

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

1
Hai @RikHic, tip yang bagus - sedang memikirkan sesuatu seperti ini; sayangnya pemformatan di atas tidak berjalan dengan benar :) Jadi saya akan mencoba dengan tag pra (tidak berfungsi) - jadi dengan lolos dari backticks maka: sed -i 's/subdomainA/subdomainB/g'` grep -ril 'subdomainA' /home/www/*` - ini masih tidak terlihat terlalu bagus, tetapi seharusnya selamat dari copypaste :) Cheers!
sdaau

4
#!/usr/local/bin/bash -x

find * /home/www -type f | while read files
do

sedtest=$(sed -n '/^/,/$/p' "${files}" | sed -n '/subdomainA/p')

    if [ "${sedtest}" ]
    then
    sed s'/subdomainA/subdomainB/'g "${files}" > "${files}".tmp
    mv "${files}".tmp "${files}"
    fi

done

4

Menurut posting blog ini :

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

Bagaimana Anda bisa lolos dari tebasan /? Misalnya, saya ingin mengganti alamat IP: xxx.xxx.xxx.xxxuntukxxx.xxx.xxx.xxx/folder
Pathros

Anda dapat melarikan diri /dengan \. Misalnya:find . -type f | xargs perl -pi -e 's/xxx.xxx.xxx.xxx\/folder/newtext/g;'
J.Hpour

3

Jika Anda tidak keberatan menggunakan vimbersama-sama dengan grepatau findalat, Anda bisa menindaklanjuti jawaban yang diberikan oleh pengguna Gert di tautan ini -> Bagaimana cara melakukan penggantian teks dalam hierarki folder besar? .

Inilah kesepakatannya:

  • grep secara rekursif untuk string yang ingin Anda ganti di jalur tertentu, dan ambil hanya path lengkap dari file yang cocok. (itu akan menjadi $(grep 'string' 'pathname' -Rl).

  • (opsional) jika Anda ingin melakukan pra-backup file-file itu pada direktori terpusat mungkin Anda dapat menggunakan ini juga: cp -iv $(grep 'string' 'pathname' -Rl) 'centralized-directory-pathname'

  • setelah itu Anda dapat mengedit / mengganti sesuka hati dalam vimmengikuti skema yang mirip dengan yang disediakan pada tautan yang diberikan:

    • :bufdo %s#string#replacement#gc | update

2

Sekolah yang agak tua tetapi ini bekerja pada OS X.

Ada beberapa trik:

• Hanya akan mengedit file dengan ekstensi di .slsbawah direktori saat ini

.harus melarikan diri untuk memastikan sedtidak mengevaluasi mereka sebagai "karakter apa pun"

,digunakan sebagai sedpembatas sebagai ganti dari yang biasa/

Juga perhatikan ini untuk mengedit template Jinja untuk melewati variabledi jalur import(tapi ini di luar topik).

Pertama, verifikasi perintah sed Anda melakukan apa yang Anda inginkan (ini hanya akan mencetak perubahan ke stdout, itu tidak akan mengubah file):

for file in $(find . -name *.sls -type f); do echo -e "\n$file: "; sed 's,foo\.bar,foo/bar/\"+baz+\"/,g' $file; done

Edit perintah sed sesuai kebutuhan, setelah Anda siap untuk melakukan perubahan:

for file in $(find . -name *.sls -type f); do echo -e "\n$file: "; sed -i '' 's,foo\.bar,foo/bar/\"+baz+\"/,g' $file; done

Catat -i ''dalam perintah sed , saya tidak ingin membuat cadangan dari file asli (seperti yang dijelaskan dalam In-place edit dengan sed pada OS X atau dalam komentar Robert Lujo di halaman ini).

Selamat seding orang!


2

hanya untuk menghindari berubah juga

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

tetapi tetap saja

  • subdomainA.example.com.IsIt.good

(mungkin tidak baik dalam ide di balik root domain)

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

2

Saya hanya menggunakan atasan:

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>)" 

plus satu untuk `'*. [c | cc | cp | cpp | m | mm | h]'`
FractalSpace

2

Inilah versi yang harus lebih umum daripada kebanyakan; itu tidak memerlukan find(menggunakan dugantinya), misalnya. Memang diperlukan xargs, yang hanya ditemukan di beberapa versi Plan 9 (seperti 9front)

 du -a | awk -F' '  '{ print $2 }' | xargs sed -i -e 's/subdomainA\.example\.com/subdomainB.example.com/g'

Jika Anda ingin menambahkan filter seperti ekstensi file gunakan grep:

 du -a | grep "\.scala$" | awk -F' '  '{ print $2 }' | xargs sed -i -e 's/subdomainA\.example\.com/subdomainB.example.com/g'

1

Untuk Qshell (qsh) di IBMi, bukan bash seperti yang ditandai oleh OP.

Keterbatasan perintah qsh:

  • find tidak memiliki opsi -print0
  • xargs tidak memiliki opsi -0
  • sed tidak memiliki opsi -i

Demikian solusi dalam 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

Peringatan:

  • Solusi tidak termasuk penanganan kesalahan
  • Bukan Bash yang ditandai oleh OP

Ini memiliki beberapa masalah sial dengan mengutip serta membaca baris for.
tripleee

1

Jika Anda ingin menggunakan ini tanpa sepenuhnya menghancurkan repositori SVN Anda, Anda dapat memberi tahu 'find' untuk mengabaikan semua file tersembunyi dengan melakukan:

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

Tanda kurung tampaknya berlebihan. Ini sebelumnya memiliki kesalahan pemformatan yang membuatnya tidak dapat digunakan (rendering Markdown akan memakan beberapa karakter dari regex).
tripleee

1

Menggunakan kombinasi grepdansed

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

@ tripleee Saya sedikit memodifikasi ini. Dalam hal ini output untuk perintah yang grep -Rl patterndihasilkan daftar file di mana polanya. File tidak dibaca dalam forlingkaran.
Pawel

Hah? Anda masih memiliki satu forlingkaran; jika ada nama file yang dikembalikan berisi spasi, itu tidak akan berfungsi dengan benar, karena shell tokenizes fordaftar argumen. Tapi kemudian Anda menggunakan variabel nama file tanpa tanda kutip di dalam loop, jadi itu akan pecah di sana jika Anda memperbaikinya. Mengoreksi bug yang tersisa ini akan membuat Anda identik dengan jawaban @ MadMan2064.
tripleee

@ tripleee ya, itu benar, saya melewatkan ini.
Pawel

1

Untuk mengganti semua kejadian di repositori git, Anda dapat menggunakan:

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

Lihat Daftar file dalam repo git lokal? untuk opsi lain untuk membuat daftar semua file dalam repositori. The -zpilihan memberitahu git untuk memisahkan nama file dengan byte nol, yang menjamin bahwa xargs(dengan pilihan -0) dapat memisahkan nama file, bahkan jika mereka berisi spasi atau entah apa lagi.


1
perl -p -i -e 's/oldthing/new_thingy/g' `grep -ril oldthing *`

1
Tidak menggunakan awk/ sed, tetapi perl adalah umum (kecuali embedded / sistem dengan busybox saja).
pevik

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.