Awk / sed: Kaip padaryti rekursinį paieškos / pakeitimo eilutę?

Kaip rasti ir pakeisti kiekvieną įvykį:

 subdomainA.example.com 

su

 subdomainB.example.com 

kiekviename teksto faile /home/www/ katalogo medyje (rekursyvi paieška / pakeisti).

443
18 окт. Tedd nustatytas spalio 18 d 2009-10-18 00:10 '09 0:10 2009-10-18 00:10
@ 29 atsakymai

Pastaba Negalima paleisti šios komandos aplanke, kuriame yra git repo - .git pakeitimai gali sugadinti jūsų git indeksą.

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

man find :

-print0 (tik GNU paieškai) nurodo rasti tuščią simbolį (0), o ne tarpą kaip išvesties separatorių tarp rastų kelio pavadinimų. Tai yra saugesnis variantas, jei failuose gali būti tarpų ar kito specialiojo pobūdžio. Rekomenduojama naudoti argumentą -print0, jei norite ieškoti, jei naudojate komandą -exec arba xargs („xargs“ reikalingas argumentas -0).

632
18 окт. atsakymas pateikiamas ep3static 18 oct. 2009-10-18 00:32 '09 0:32 2009-10-18 00:32

Pastaba Negalima paleisti šios komandos aplanke, kuriame yra git repo - .git pakeitimai gali sugadinti jūsų git indeksą.

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

Palyginti su kitais čia pateiktais atsakymais, tai yra paprastesnė nei dauguma, o vietoj perl naudojama sed, kuri yra pirminis klausimas.

180
18 окт. John Zwinck atsakymas, pateiktas spalio 18 d 2009-10-18 22:34 '09 10:34 val. 2009-10-18 22:34

Visi gudrybės yra beveik tokie patys, bet man patinka šis:

 find <mydir> -type f -exec sed -i 's/<string1>/<string2>/g' {} + 
  • find <mydir> : suraskite katalogą.

  • -type f :

    Failo tipas: įprastas failas

  • -exec command {} + :

    Ši parinktis -exec atlieka nurodytą komandą pasirinktuose failuose, bet komandinė eilutė sukuriama pridedant kiekvieną pasirinkto failo pavadinimą iki pabaigos; Bendras komandų skambučių skaičius bus daug mažesnis nei suderintų failų skaičius. Komandinė eilutė sukurta taip pat, kaip xargs sukuria komandų eilutes. Komandoje leidžiama naudoti tik vieną {}} egzempliorių. Komanda veikia pradiniame kataloge.

44
31 янв. atsakymas pateikiamas I159 sausio 31 d 2014-01-31 15:00 '14 15:00 val. 2014-01-31 15:00
 cd /home/www  find . -type f -print0 | xargs -0 perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g' 
37
18 окт. „ Russian Russian Oct 18“ atsakymas 2009-10-18 00:13 '09 0:13 2009-10-18 00:13

Paprasčiausias būdas man -

 grep -rl oldtext . | xargs sed -i 's/oldtext/newtext/g' 
31
13 марта '14 в 20:05 2014-03-13 20:05 atsakymą pateikė Anatolijus, kovo 13 d., 14 d., 20:05, 2014-03-13 20:05

Man paprasčiausias sprendimas prisiminti yra ngn-wiki.ru.site/questions/2977 / ... , tai yra:

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

PASTABA : -i '' išsprendžia OSX sed: 1: "...": invalid command code . problemą sed: 1: "...": invalid command code .

PASTABA . Jei yra per daug failų, kuriuos norite apdoroti, Argument list too long gausite Argument list too long . Problemų sprendimas - naudokite pirmiau aprašytą sprendimą „ find -exec arba „ xargs .

25
03 сент. Robert Lujo atsakymas 03.09. 2013-09-03 13:00 '13 13:00 val. 2013-09-03 13:00

Tiems, kurie naudoja sidabro ieškiklį ( ag )

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

Kadangi ag ignoruoja numatytąjį git / hg / svn failą / aplanką, saugu paleisti saugykloje.

15
02 сент. Atsakymą pateikė Jacob Wang 02 Sep. 2016-09-02 08:19 '16 at 8:19 2016-09-02 08:19

Vienas gražus Oneliner kaip papildomas. Naudojant git grep.

 git grep -lz 'subdomainA.example.com' | xargs -0 perl -i'' -pE "s/subdomainA.example.com/subdomainB.example.com/g" 
12
10 февр. Jimmy Kane atsakė 10 vasario mėn. 2014-02-10 22:07 '14 at 10:07 pm 2014-02-10 22:07

Tai suderinama su „git“ saugyklomis ir šiek tiek paprasčiau:

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' 

(Ačiū http://blog.jasonmeridth.com/posts/use-git-grep-to-replace-strings-in-files-in-your-git-repository/ )

9
24 июня '16 в 11:26 2016-06-24 11:26 Atsakymas duotas seddonym birželio 24 '16, 11:26 2016-06-24 11:26
 find /home/www/ -type f -exec perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g' {} + 

find /home/www/ -type f rodys visus failus iš / home / www / (ir jo pakatalogiuose). „-Exec“ vėliava nurodo, kad kiekvienas rastas failas turi paleisti šią komandą.

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

- Tai yra komandos paleidimas pagal failą (po vieną). {} pakeičiamas failų pavadinimais. + pabaigoje + nurodo find vieną komandą daugeliui failų pavadinimų.

find man“ puslapyje: „Komandinė eilutė sukurta taip, kaip xargs sukuria komandų eilutes.

Tokiu būdu galite pasiekti savo tikslą (ir tvarkyti failų pavadinimus, kuriuose yra tarpų) nenaudojant xargs -0 arba -print0 .

7
18 окт. atsakymas duotas unutbu 18 oct. 2009-10-18 19:40 '09, 07:40 pm 2009-10-18 19:40

Aš tik to reikėjo ir nepatenkina turimų pavyzdžių greičiu. Taigi aš atėjau su savo:

 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 yra labai efektyvus ieškant suderinamų failų. Ši komanda pakeitė ~ 145 000 failų su vėju, o kiti paėmė tiek daug laiko, kad negalėjau laukti, kol jie bus baigti.

7
10 апр. Henno atsakymas, pateiktas balandžio 10 d 2011-04-10 03:25 '11 at 3:25 2011-04-10 03:25

Jei norite sutrumpinti rekursiškus failus, galite grep savo eilutės pavyzdį:

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

Jei paleisite „ man grep , pastebėsite, kad galite nurodyti --exlude-dir="*.git" vėliavą, jei norite praleisti paiešką .git kataloguose, vengdami problemų su git indeksais, kaip kiti mandagiai nurodė.

Mes atnešime jus į:

 grep -rl --exclude-dir="*.git" <oldstring> /path/to/folder | xargs sed -is^<oldstring>^<newstring>^g 
6
22 авг. atsakymas duotas domdambrogia 22 rug . 2017-08-22 23:28 '17, 23:28 pm 2017-08-22 23:28

Pabandykite atlikti šiuos veiksmus:

 sed -i 's/subdomainA/subdomainB/g' `grep -ril 'subdomainA' *` 
3
28 июня '10 в 15:09 2010-06-28 15:09 atsakymą pateikė „ RikHic “ birželio 10 d. 15:09 2010-06-28 15:09
 #!/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 
3
05 нояб. atsakymas pateikiamas petrus4 05 lapkričio. 2013-11-05 20:06 '13, 20:06, 2013-11-05 20:06

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

Manau, kad dauguma žmonių nežino, kad gali kažką perkelti į „perskaitytą“ failą ir išvengti šių nemalonių argumentų-print0, o failų pavadinimų tarpai išsaugomi.

Toliau pridėjus echo prieš sed'ą, galėsite pamatyti, kurie failai bus pakeisti prieš tai.

3
29 мая '15 в 8:34 2015-05-29 08:34 atsakymas duotas MadMan2064 gegužės 29 d. 15 val. 8:34 2015-05-29 08:34

Jei nenorite naudoti „ vim su „ grep arba find įrankių, galite sekti „Gert“ naudotojo pateiktą atsakymą šioje nuorodoje → Kaip pakeisti tekstą dideliame aplanko hierarchijoje? .

Čia yra sandoris:

  • recursively grep už eilutę, kurią norite pakeisti tam tikru keliu, ir paimkite tik visą atitinkamo failo kelią. (tai bus $(grep 'string' 'pathname' -Rl) .

  • (neprivaloma), jei norite atlikti išankstinę šių failų atsarginę kopiją centralizuotame kataloge, taip pat galite naudoti šį failą: cp -iv $(grep 'string' 'pathname' -Rl) 'centralized-directory-pathname'

  • po to galite redaguoti / pakeisti pageidaujamą vim pagal schemą, panašią į tai, kas nurodyta toliau esančioje nuorodoje:

    • :bufdo %s#string#replacement#gc | update
2
02 марта '15 в 14:32 2015-03-02 14:32 atsakymą pateikė mzcl-mn kovo 2 d. 15 d. 14:32 2015-03-02 14:32

Šiek tiek senoji mokykla, tačiau ji dirbo OS X.

Yra keletas klaidų:

.sls tik failus, kurių plėtinys yra .sls dabartiniame kataloge.

. turi būti išvengta, kad užtikrintų, jog sed nėra vertinami kaip „bet kokie simboliai“

, naudojamas kaip sed separatorius vietoj įprastų /

Taip pat atkreipkite dėmesį, kad tai redaguoja „Jinja“ šabloną, kad perduotų variable import kelyje (bet tai nėra tema).

Pirmiausia įsitikinkite, kad jūsų „sed“ komanda daro tai, ko norite (tai tik spausdins pakeitimus į „stdout“, ji nepakeis failų)

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

Redaguokite sed komandą, kai tik esate pasiruošę atlikti pakeitimus:

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

Atkreipkite dėmesį į -i '' į „ sed“ komandą, aš nenorėjau kurti atsarginių šaltinių failų (kaip aprašyta „ Redagavimas vietoje su„ OS X “ arba„ Robert Lujo “komentarą šiame puslapyje).

Laimingi žmonės sedanai!

1
21 нояб. Atsakymą pateikė Raphvanns lapkričio 21 d. 2016-11-21 22:41 '16 at 10:41 pm 2016-11-21 22:41

išvengti pokyčių.

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

bet vis tiek

  • subdomainA.pavyzdys.com.Ji gerai

(galbūt ne labai gerai domeno šaknies idėja)

 find /home/www/ -type f -exec sed -i 's/\bsubdomainA\.example\.com\b/\1subdomainB.example.com\2/g' {} \; 
1
31 марта '17 в 14:54 2017-03-31 14:54 atsakymą pateikė „ NeronLeVelu“ kovo 31 d. 17 val. 14:54 2017-03-31 14:54

Jei norite išspręsti šią problemą, galite naudoti awk, kaip parodyta žemiau.

 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 

Tikiuosi, kad tai padės jums!

1
04 июля '16 в 14:53 2016-07-04 14:53 atsakymas pateikiamas saratui kumarui liepos 4 d. 16, 14:53 2016-07-04 14:53

Naudojant grep ir sed

 for pp in $(grep -Rl looking_for_string) do sed -i 's/looking_for_string/something_other/g' "${pp}" done 
1
15 янв. atsakymas pateikiamas Pawel sausio 15 d 2015-01-15 14:38 '15, 14:38, 2015-01-15 14:38

„Qshell“ (qsh), skirta „IBMi“, o ne kaip „OP“.

„Qsh“ komandų apribojimai:

  • rasti nėra -print0 parinkties
  • xargs neturi -0 parinkties
  • sed neturi -i parinkties

Taigi sprendimas „qsh“ yra:

  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 

Perspėjimai:

  • Sprendimas pašalina klaidų apdorojimą.
  • Ne bash pažymėtas OP
1
26 апр. atsakymas, kurį pateikė Christoffas Erasmus 2014-04-26 00:56 '14 ne 0:56 2014-04-26 00:56

Jei norite tai naudoti visiškai nepažeisdami savo SVN saugyklos, galite pasakyti „rasti“, kad ignoruotumėte visus paslėptus failus:

 find . \( ! -regex '.*/\..*' \) -type f -print0 | xargs -0 sed -i 's/subdomainA.example.com/subdomainB.example.com/g' 
1
30 окт. atsakymą pateikė Marcus Floyd 30 d. 2014-10-30 07:18 '14 at 7:18 2014-10-30 07:18

Jei norite pakeisti visus „git“ saugyklos įrašus, galite naudoti:

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

Žr. Vietinio git repo failų sąrašą? kitoms parinktims, leidžiančioms išvardyti visus saugykloje esančius failus. „ -z parinktis nurodo „Git“ atskirti failų pavadinimus su nuliniu baitu, kuris užtikrina, kad xargs (su -0 pasirinkimu) gali atskirti failų pavadinimus, net jei jame yra tarpų arba kažkas kito.

0
31 марта '17 в 12:47 2017-03-31 12:47 atsakymą pateikė Perseids , kovo 31 d. 17, 12:47 2017-03-31 12:47
 perl -p -i -e 's/oldthing/new_thingy/g' `grep -ril oldthing *` 
0
20 июля '17 в 14:57 2017-07-20 14:57 Atsakymas, kurį pateikė Sheena, liepos 20, 17, 14:57 2017-07-20 14:57

Tai yra geriausias sprendimas, kurį rasta OSX ir Windows (msys2). Turėtų dirbti su visa, ką gnu sed gali gauti. Praleidžia .git katalogus, todėl ji nepažeis jūsų kontrolinių sumų.

„Mac“ pirmiausia įdiekite „coreutils“ ir įsitikinkite, kad „gsed“ yra kelyje -

 brew install coreutils 

Tada naudoju šią funkciją savo zshrc / bashrc →

 replace-recursive() { hash gsed 2>/dev/null  local SED_CMD="gsed" || SED_CMD="sed" find . -type f -name "*.*" -not -path "*/.git*.* 
0
17 марта '17 в 16:40 2017-03-17 16:40 atsakymas yra matematinis, kovo 17 d. 17, 16:40 2017-03-17 16:40

Jei norite pakeisti visą turinio atitikimo eilutę_1 su visų .c ir .h failų eilute_2 dabartiniame kataloge ir pakatalogiuose (išskyrus .git /) .

Jis veikia „Mac“:

 find . -type f -path "*.git*" -prune -o -name '*\.[ch]' -exec \ sed -i '' -e 's/'$1'/'$2'/g' {} + 

Tai turėtų veikti „Linux“ (dar neišbandyta):

 find . -type f -path "*.git*" -prune -o -name '*\.[ch]' -exec \ sed -i 's/string_1/string_2/g' {} + 
0
Atsakymą pateikia Klas. 22 янв. S 22 d 2017-01-22 16:22 '17 ne 4:22 2017-01-22 16:22

Kiti klausimai apie „ žymes arba „ Užduoti klausimą“