Jak miałbym użyć sed, aby usunąć wszystkie wiersze w pliku tekstowym zawierającym określony ciąg?
shell
sed
text-parsing
in-place
Mechaniczna pomarańcza
źródło
źródło
sed '/pattern to match/d' ./infile > ./newfile
lub jeśli chcesz dokonać edycji w miejscu, możesz dodać-i
flagę do sed jak wsed -i '/pattern to match/d' ./infile
. Zauważ, że-i
flaga wymaga GNU sed i nie jest przenośnased -i.backup '/pattern to match/d' ./infile
) Dzięki temu wprowadziłem zmiany w miejscu.sed
do 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
Rubin (1.9+)
Perl
Shell (bash 3.2 i nowsze)
GNU grep
I oczywiście
sed
(wydruk odwrotny jest szybszy niż faktyczne usunięcie):źródło
sed
przykład mieć inny problem, to tylko greps! powinno być coś takiegosed -n -i '/pattern/!p' file
.grep -v "pattern" file > temp; mv temp file
moż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.txt
prawdziwe 0m9.294s. sed! p:time sed -i '' -n '/6543210/!p' foo.txt
real 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
lub
Pierwsze polecenie i tak trwa 3 razy dłużej na moim komputerze.
źródło
sed '/pattern/d' filename > filename2; mv filename2 filename
Łatwy sposób na zrobienie tego z GNU
sed
:źródło
-r
opcję (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):gdzie:
+
wykonuje dane polecenie Ex (man ex
), tak samo jak to,-c
które wykonujewq
(zapisz i wyjdź)g/match/d
- Polecenie Ex do usuwania linii z danymmatch
, 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 dla
ex
.Różnica
sed
polega na tym, że: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.źródło
man ex
daje mi mężczyznęvim
, wydaje się,ex
jest częścią vim ... gdybym rozumieć prawo to oznacza dla składni wzórmatch
jest 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
$file
jest plik, w którym konieczne jest usunięcie, i$pattern
wzó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.źródło
sed
wymaga 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
grep
wydaje się być około 15 razy szybszy niżsed
metoda 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:
źródło
Możesz także użyć tego:
Tutaj
-v
wydrukuje się tylko inny wzór niż twój (co oznacza dopasowanie odwrócone).źródło
Aby uzyskać podobny wynik,
grep
możesz to zrobić:źródło
bash
powłoki lub podobnego (nietcsh
).SED:
'/James\|John/d'
-n '/James\|John/!p'
AWK:
'!/James|John/'
/James|John/ {next;} {print}
GREP:
-v 'James\|John'
źródło
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).
źródło
echo -e "/thing_to_delete\ndd\033:x\n" | vim file_to_edit.txt
źródło
Na wypadek, gdyby ktoś chciał to zrobić dla dokładnego dopasowania ciągów, możesz użyć
-w
flagi 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:Działa również z
-f
flagą, 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”:źródło
-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 $.
źródło
aby wyświetlić traktowany tekst w konsoli
aby zapisać traktowany tekst w pliku
aby dołączyć przetworzone informacje tekstowe do istniejącego pliku
aby leczyć już przetworzony tekst, w tym przypadku usuń więcej wierszy tego, co zostało usunięte
| more
pokaże tekst kawałkami jednej strony na raz.źródło
Można używać starych dobrych
ed
edytować plik w podobny sposób do odpowiedzi , które wykorzystujeex
. Dużą różnicą w tym przypadku jest to, żeed
przyjmuje polecenia za pomocą standardowego wejścia, a nie argumentów wiersza poleceń, jakex
można. Kiedy używasz go w skrypcie, zwykłym sposobem na przystosowanie się do tego jest użycieprintf
poleceń do niego:lub z heredoc:
źródło