Jak usunąć z pliku tekstowego wszystkie linie zawierające określony ciąg znaków?
Jak użyć sed, aby usunąć wszystkie linie w pliku tekstowym, które zawierają określony ciąg znaków?
18 answers
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 BSD sed:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-27 09:57:09
Oprócz sed
istnieje wiele innych sposobów usuwania linii z określonym ciągiem znaków:
AWK
awk '!/pattern/' file > temp && mv temp file
Ruby (1.9+)
ruby -i.bak -ne 'print if not /test/' file
Perl
perl -ni.bak -e "print unless /pattern/" file
Shell (bash 3.2 i nowsze)
while read -r line
do
[[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file
GNU grep
grep -v "pattern" file > temp && mv temp file
I oczywiście sed
(drukowanie odwrotności jest szybsze niż rzeczywiste usunięcie):
sed -n '/pattern/!p' file
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-15 22:06:06
Możesz użyć sed, aby zastąpić wiersze w pliku. Jednak wydaje się, że jest to znacznie wolniejsze niż użycie grepa do odwrotnej zmiany do drugiego pliku, a następnie przeniesienie drugiego pliku nad oryginał.
Np.
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 mojej maszynie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-19 15:07:10
Prosty sposób na to, z GNU sed
:
sed --in-place '/some string here/d' yourfile
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-11 23:50:54
Możesz rozważyć użycie ex
(który jest standardowym uniksowym edytorem opartym na poleceniach):
ex +g/match/d -cwq file
Gdzie:
-
+
wykonuje polecenie Ex (man ex
), tak samo jak-c
które wykonujewq
(write and quit) -
g/match/d
- Ex komenda do usuwania linii o podanymmatch
, patrz: moc g
Powyższy przykład jest zgodną z POSIX metodą edycji pliku w miejscu, zgodnie z poniższym postem w Unix.SE i Specyfikacja POSIX na ex
.
Różnica z sed
jest taka, że:
sed
jest S tream ED itor, a nie edytor plików.BashFAQ
Chyba, że lubisz kod nieportable, I / O overhead i inne złe skutki uboczne. Tak więc w zasadzie niektóre parametry (takie jak in-place/-i
) są niestandardowymi rozszerzeniami FreeBSD i mogą nie być dostępne na innych systemach operacyjnych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-15 22:08:57
Zmagałem się z tym na Macu. Poza tym musiałem to zrobić za pomocą wymiany zmiennych.
Więc użyłem:
sed -i '' "/$pattern/d" $file
Gdzie $file
jest plikiem, w którym potrzebne jest usunięcie, a $pattern
jest wzorcem, który należy dopasować do usunięcia.
Wybrałem ''
z tego komentarza.
Należy tutaj 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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-15 22:15:45
Możesz również użyć tego:
grep -v 'pattern' filename
Tutaj -v
wydrukuje tylko inny wzór niż twój wzór (co oznacza odwrócenie dopasowania).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-15 22:07:13
Zrobiłem mały benchmark z plikiem, który zawiera około 345 000 linii. Sposób z grep
wydaje się być około 15 razy szybszy niż metoda sed
w tym przypadku.
Próbowałem zarówno z ustawieniem LC_ALL=C, jak i bez niego, nie zmienia to znacząco czasu. Szukany ciąg (CDGA_00004.pdbqt.gz.tar) jest gdzieś w środku pliku.
Oto komendy i timingi:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-19 12:45:18
Aby uzyskać wynik inplace like z grep
możesz to zrobić:
echo "$(grep -v "pattern" filename)" >filename
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-13 19:24:59
SED:
AWK:
GREP:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-20 13:28:37
perl -i -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3
Pierwsze polecenie edytuje plik(y) w miejscu (-i).
Drugie polecenie robi to samo, ale zachowuje kopię lub kopię zapasową oryginalnych plików przez dodanie .bk do nazw plików (.bk można zmienić na cokolwiek).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-08 12:07:39
echo -e "/thing_to_delete\ndd\033:x\n" | vim file_to_edit.txt
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-16 23:51:31
Na wypadek, gdyby ktoś chciał to zrobić dla dokładnych dopasowań łańcuchów, możesz użyć znacznika -w
w grep-w dla całości. Oznacza to, że na przykład, jeśli chcesz usunąć linie z numerem 11, ale zachować linie z numerem 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 flagą -f
, Jeśli chcesz wykluczyć kilka dokładnych wzorców naraz. Jeśli "czarna lista" jest plikiem z kilkoma wzorami w każdej linii, którą chcesz usunąć z"pliku":
grep -w -v -f blacklist file
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-15 22:18:52
cat filename | grep -v "pattern" > filename.1
mv filename.1 filename
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-29 16:45:24
Można również usunąć zakres linii w pliku. Na przykład, aby usunąć procedury przechowywane w pliku SQL.
sed '/CREATE PROCEDURE.*/,/END ;/d' sqllines.sql
Spowoduje usunięcie wszystkich linii pomiędzy procedurą CREATE I END ;.
Wyczyściłem wiele plików sql za pomocą tego polecenia sed.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-02 01:49:27
Aby pokazać traktowany tekst w konsoli
cat filename | sed '/text to remove/d'
Aby zapisać traktowany tekst do pliku
cat filename | sed '/text to remove/d' > newfile
Aby dodać informacje tekstowe do istniejącego pliku
cat filename | sed '/text to remove/d' >> newfile
Aby potraktować 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
| more
wyświetli tekst w kawałkach po jednej stronie na raz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-27 20:19:32
Możesz użyć starego, dobrego ed
, aby edytować plik w sposób podobny do odpowiedzi , która używa ex
. Duża różnica w tym przypadku polega na tym, że ed
pobiera swoje polecenia poprzez standardowe wejście, a nie jako argumenty linii poleceń, jak ex
can. W przypadku użycia go w skrypcie, zwyczajowym sposobem na rozwiązanie tego problemu jest użycie printf
do przesyłania komend do niego:
printf "%s\n" "g/pattern/d" w | ed -s filename
Lub z heredoc:
ed -s filename <<EOF
g/pattern/d
w
EOF
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-19 14:21:01
Co ciekawe, przyjęta odpowiedź nie odpowiada bezpośrednio na pytanie. Pytanie pyta o użycie sed do zastąpienia string, ale odpowiedź wydaje się zakładać wiedzę o tym, jak przekształcić dowolny łańcuch w regex.
Wiele bibliotek języka programowania posiada funkcję do wykonywania takiej transformacji, np.
python: re.escape(STRING)
ruby: Regexp.escape(STRING)
java: Pattern.quote(STRING)
Ale jak to zrobić w wierszu poleceń?
Ponieważ jest to pytanie zorientowane na sed, jednym z podejść byłoby użycie sed:
sed 's/\([\[/({.*+^$?]\)/\\\1/g'
Więc mając dowolny łańcuch $STRING możemy napisać coś w stylu:
re=$(sed 's/\([\[({.*+^$?]\)/\\\1/g' <<< "$STRING")
sed "/$re/d" FILE
Lub jako jednoliterowy:
sed "/$(sed 's/\([\[/({.*+^$?]\)/\\\1/g' <<< "$STRING")/d"
Z wariacjami opisanymi w innym miejscu na tej stronie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-23 01:47:33