grep plik i potokuj wyjście do sed i przechowuj wyjście sed w pliku

3

Zawartość source.txt:

gold  green white black blue
yellow magenta brown 
tram kilo charlie tango

Cześć wszystkim! Muszę rozwiązać zagadkę.

Próbuję uruchomić mały skrypt, aby grep pliku source.txt, grepwyjście potoku, aby sedzastąpić ciąg i zapisać tę linię w nowym plikupol.txt

grep -l "gold" source.txt | xargs sed  's/green/red/' >  pol.txt

Zamiast mieć jedyną tę linię w pol.txt:

gold  red white black blue

Mam cały sam plik z ciągiem, który zastąpiłem

gold  red white black blue
yellow magenta brown 
tram kilo charlie tango

Kiedy -lusuwam opcję z polecenia grep, mam to i oczywiście nic w pol.txt

sed: can't read gold: No such file or directory
sed: can't read green: No such file or directory
sed: can't read white: No such file or directory
sed: can't read black: No such file or directory
sed: can't read blue: No such file or directory

grep jest potrzebny jako tester i niestety opcja „jeśli” nie jest opcją.

Napędzany
źródło
Na jakim systemie operacyjnym jesteś? I z czym został source.txtzapisany plik? Wydaje mi się, że może to być pomieszanie między zwrotami karetki a pomieszaniem kanałów i linii.
JakeGould
Jak pokazuje odpowiedź John1234, prawie nigdy nie trzeba używać razem grepi sedrazem - sedsama prawdopodobnie prawdopodobnie może zrobić wszystko, co oba programy mogą zrobić razem. Jeśli masz problem z wieloma plikami wejściowymi i potrzebujesz przetworzyć tylko te, które zawierają „złoto”, prawdopodobnie powinieneś to wyjaśnić; w przeciwnym razie ludzie, którzy próbują odpowiedzieć na twoje pytanie, mają jedną rękę związaną za plecami. (Proszę nie odpowiadać w komentarzach; edytuj swoje pytanie, aby było jaśniejsze i bardziej kompletne.) Jak wyjaśnia Satya Mishra, grep -l "gold" source.txtwyświetli source.txt  … (ciąg dalszy)
G-Man
(Ciąg dalszy)… jeśli plik zawiera słowo „złoto” (i nic, jeśli nie zawiera). Jeśli jedyną rzeczą, którą zapisujesz w potoku, jest source.txtnazwa pliku, nie ma mowy, aby proces po prawej stronie potoku wiedział, że chcesz, aby przetwarzał tylko linie zawierające „złoto”, chyba że wbudujesz to w polecenie (jak pokazuje John). (Jego komendę można trochę uprościć, aby sed -n '/gold/s/green/red/p' source.txt. A jeśli potrafisz pisać sed 's/green/red/', czy to naprawdę jest tak „przerażające”, że utrzymanie go będzie „bolesne”?)
G-Man

Odpowiedzi:

4

Aby wybrać dowolną linię zawierającą goldod source.txt i zastąpić pierwsze wystąpienie greenz red:

$ sed  -n '/gold/{s/green/red/; p}' source.txt 
gold  red white black blue

Aby zapisać to w pliku:

sed  -n '/gold/{s/green/red/; p}' source.txt  >pol.txt

Jak to działa

  • -n mówi sed, aby nie drukował linii, chyba że wyraźnie o to poprosimy.

  • /gold/wybiera linie pasujące do wyrażenia regularnego gold.

  • s/green/red/ wykonuje podstawienie

  • p odbitki.

Korzystanie z awk

Z tą samą logiką:

$ awk '/gold/{gsub(/green/, "red"); print}' source.txt 
gold  red white black blue

Korzystanie z grep

Jeśli z powodów jeszcze nie wyjaśnionych jesteśmy zmuszeni do korzystania z potoku grep, spróbuj:

$ grep -l --null "gold" source.txt | xargs -0 sed  -n '/gold/s/green/red/p'
gold  red white black blue
John1024
źródło
dzięki John za twój wkład, ale grep jest potrzebny. Grep będzie używany jako tester przed przekazaniem wyjścia do sed.
Driven
1
@Driven Dlaczego uważasz, że grep jest potrzebny jako tester? sed jest w stanie wykonać ten sam test. Chyba że masz jakieś inne wymagania, które nie zostały jeszcze wyjaśnione?
John1024,
Planuję zautomatyzować ten proces za pomocą pętli for przez kilka plików.
Driven
Aby przetworzyć kilka plików, nie ma potrzeby używania forpętli. Sed może przyjmować wiele nazw plików w jednym wierszu poleceń. (Jeśli wciąż jest więcej wymagań, zamiast ujawniać swój cel fragmentarycznie, równie dobrze możesz po prostu określić je wszystkie naraz.)
John1024
@Driven Dodałem wersję z potokiem grep.
John1024,
1

grep -l "gold" source.txtwyświetli, source.txtjeśli plik zawiera słowo gold xargs sed 's/green/red/', sed 's/green/red/' source.txta końcowe przekierowanie zapisze wynik w twoich wynikach.

Jeśli dobrze rozumiem twoją intencję, potrzebujesz następującego polecenia:

sed -n '/gold/s/green/red/p' source.txt > pol.txt

Te /gold/linie zaznaczane są dopasowane goldi skomenda robi wymiany chcesz.

Satya Mishra
źródło