Jak miałbym użyć sed, aby usunąć wszystkie wiersze w pliku tekstowym zawierającym określony ciąg?
Jak miałbym użyć sed, aby usunąć wszystkie wiersze w pliku tekstowym zawierającym określony ciąg?
Odpowiedzi:
Aby usunąć linię i wydrukować wyjście na standardowe wyjście:
sed '/pattern to match/d' ./infile
Aby bezpośrednio zmodyfikować plik - nie działa z sedem BSD:
sed -i '/pattern to match/d' ./infile
To samo, ale dla BSD sed (Mac OS X i FreeBSD) - nie działa z GNU sed:
sed -i '' '/pattern to match/d' ./infile
Aby bezpośrednio zmodyfikować plik (i utworzyć kopię zapasową) - działa z BSD i GNU sed:
sed -i.bak '/pattern to match/d' ./infile
sed '/pattern to match/d' ./infile > ./newfilelub jeśli chcesz dokonać edycji w miejscu, możesz dodać -iflagę do sed jak w sed -i '/pattern to match/d' ./infile. Zauważ, że -iflaga wymaga GNU sed i nie jest przenośna
sed -i.backup '/pattern to match/d' ./infile) Dzięki temu wprowadziłem zmiany w miejscu.
seddo plików, które nie są kontrolowane przez wersję.
sed -i '' '/pattern/d' ./infile.
Istnieje wiele innych sposobów usuwania linii z określonym ciągiem znaków sed:
awk '!/pattern/' file > temp && mv temp file
ruby -i.bak -ne 'print if not /test/' file
perl -ni.bak -e "print unless /pattern/" file
while read -r line
do
[[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file
grep -v "pattern" file > temp && mv temp file
I oczywiście sed(wydruk odwrotny jest szybszy niż faktyczne usunięcie):
sed -n '/pattern/!p' file
sedprzykład mieć inny problem, to tylko greps! powinno być coś takiego sed -n -i '/pattern/!p' file.
grep -v "pattern" file > temp; mv temp filemoże to dotyczyć niektórych innych przykładów w zależności od wartości zwracanej.
seq -f %f 10000000 >foo.txt. sed d: time sed -i '' '/6543210/d' foo.txtprawdziwe 0m9.294s. sed! p: time sed -i '' -n '/6543210/!p' foo.txtreal 0m13.671s. (W przypadku mniejszych plików różnica jest większa.)
Możesz użyć sed, aby zamienić linie w pliku. Wydaje się jednak, że jest znacznie wolniejszy niż użycie grep dla odwrotności do drugiego pliku, a następnie przeniesienie drugiego pliku na oryginał.
na przykład
sed -i '/pattern/d' filename
lub
grep -v "pattern" filename > filename2; mv filename2 filename
Pierwsze polecenie i tak trwa 3 razy dłużej na moim komputerze.
sed '/pattern/d' filename > filename2; mv filename2 filename
Łatwy sposób na zrobienie tego z GNU sed:
sed --in-place '/some string here/d' yourfile
-ropcję (lub -E, w zależności od wersji). Umożliwia to korzystanie z regex metaznakami +, ?, {...}i (...).
Możesz rozważyć użycie ex(który jest standardowym edytorem uniksowym opartym na poleceniach):
ex +g/match/d -cwq file
gdzie:
+wykonuje dane polecenie Ex ( man ex), tak samo jak to, -cktóre wykonuje wq(zapisz i wyjdź)g/match/d- Polecenie Ex do usuwania linii z danym match, patrz: Moc gPowyższy przykład jest zgodną z POSIX metodą edycji na miejscu pliku zgodnie z tym postem w specyfikacji Unix.SE i POSIX dlaex .
Różnica sedpolega na tym, że:
sedto iterator S tream ED , a nie edytor plików. BashFAQ
Chyba że podoba Ci się nieobsługiwany kod, narzut I / O i inne złe skutki uboczne. Zasadniczo niektóre parametry (takie jak na miejscu / -i) są niestandardowymi rozszerzeniami FreeBSD i mogą nie być dostępne w innych systemach operacyjnych.
man exdaje mi mężczyznę vim, wydaje się, exjest częścią vim ... gdybym rozumieć prawo to oznacza dla składni wzór matchjest vimregex.com która jest podobna, ale różni się od POSIX PCRE i smaków?
:g to polecenie zgodne z POSIX, z pewnymi niewielkimi różnicami . Zakładam, że PCRE było na nim oparte.
Walczyłem z tym na Macu. Dodatkowo musiałem to zrobić, używając zmiennej zamiany.
Więc użyłem:
sed -i '' "/$pattern/d" $file
gdzie $filejest plik, w którym konieczne jest usunięcie, i $patternwzór, który należy dopasować do usunięcia.
Wybrałem ''z tego komentarza .
Należy zwrócić uwagę na użycie podwójnych cudzysłowów w "/$pattern/d". Zmienna nie będzie działać, gdy użyjemy pojedynczych cudzysłowów.
sedwymaga parametru po -i, więc jeśli nie chcesz kopii zapasowej, nadal musisz dodać pusty ciąg:-i ''
sed -i "/$pattern/d" $file. Dziękuję za Twoją odpowiedź.
Zrobiłem mały test porównawczy z plikiem, który zawiera około 345 000 linii. Sposób z grepwydaje się być około 15 razy szybszy niż sedmetoda w tym przypadku.
Próbowałem zarówno z, jak i bez ustawienia LC_ALL = C, wydaje się, że nie zmienia to znacząco czasów. Wyszukiwany ciąg (CDGA_00004.pdbqt.gz.tar) znajduje się gdzieś pośrodku pliku.
Oto polecenia i czasy:
time sed -i "/CDGA_00004.pdbqt.gz.tar/d" /tmp/input.txt
real 0m0.711s
user 0m0.179s
sys 0m0.530s
time perl -ni -e 'print unless /CDGA_00004.pdbqt.gz.tar/' /tmp/input.txt
real 0m0.105s
user 0m0.088s
sys 0m0.016s
time (grep -v CDGA_00004.pdbqt.gz.tar /tmp/input.txt > /tmp/input.tmp; mv /tmp/input.tmp /tmp/input.txt )
real 0m0.046s
user 0m0.014s
sys 0m0.019s
Możesz także użyć tego:
grep -v 'pattern' filename
Tutaj -vwydrukuje się tylko inny wzór niż twój (co oznacza dopasowanie odwrócone).
perl -i -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3
Pierwsze polecenie edytuje plik (i) w miejscu (-i).
Drugie polecenie robi to samo, ale zachowuje kopię lub kopię zapasową oryginalnych plików, dodając .bk do nazw plików (.bk można zmienić na dowolne).
Na wypadek, gdyby ktoś chciał to zrobić dla dokładnego dopasowania ciągów, możesz użyć -wflagi w grep - w dla całości. To znaczy, na przykład, jeśli chcesz usunąć linie o numerze 11, ale zachowaj linie o numerze 111:
-bash-4.1$ head file
1
11
111
-bash-4.1$ grep -v "11" file
1
-bash-4.1$ grep -w -v "11" file
1
111
Działa również z -fflagą, jeśli chcesz wykluczyć kilka dokładnych wzorów jednocześnie. Jeśli „czarna lista” to plik z kilkoma wzorami w każdej linii, który chcesz usunąć z „pliku”:
grep -w -v -f blacklist file
-w, --word-regexp Select only those lines containing matches that form whole words.vs.-x, --line-regexp Select only those matches that exactly match the whole line. For a regular expression pattern, this is like parenthesizing the pattern and then surrounding it with ^ and $.
cat filename | grep -v "pattern" > filename.1
mv filename.1 filename
aby wyświetlić traktowany tekst w konsoli
cat filename | sed '/text to remove/d'
aby zapisać traktowany tekst w pliku
cat filename | sed '/text to remove/d' > newfile
aby dołączyć przetworzone informacje tekstowe do istniejącego pliku
cat filename | sed '/text to remove/d' >> newfile
aby leczyć już przetworzony tekst, w tym przypadku usuń więcej wierszy tego, co zostało usunięte
cat filename | sed '/text to remove/d' | sed '/remove this too/d' | more
| morepokaże tekst kawałkami jednej strony na raz.
Można używać starych dobrych ededytować plik w podobny sposób do odpowiedzi , które wykorzystuje ex. Dużą różnicą w tym przypadku jest to, że edprzyjmuje polecenia za pomocą standardowego wejścia, a nie argumentów wiersza poleceń, jak exmożna. Kiedy używasz go w skrypcie, zwykłym sposobem na przystosowanie się do tego jest użycie printfpoleceń do niego:
printf "%s\n" "g/pattern/d" w | ed -s filename
lub z heredoc:
ed -s filename <<EOF
g/pattern/d
w
EOF