Usuwanie linii w pliku tekstowym zawierających 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?

Author: codeforester, 2011-03-23

14 answers

Aby usunąć linię I wydrukować wyjście na standardowe wyjście:

sed '/pattern to match/d' ./infile

Aby bezpośrednio zmodyfikować plik:

sed -i '/pattern to match/d' ./infile

Aby bezpośrednio zmodyfikować plik (i utworzyć kopię zapasową):

sed -i.bak '/pattern to match/d' ./infile

Dla użytkowników Mac OS X i FreeBSD:

sed -i '' '/pattern/d' ./infile
 2075
Author: SiegeX,
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-07 12:22:11

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
 543
Author: kurumi,
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.

 192
Author: slashdottir,
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
 54
Author: Kevin Nguyen,
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 wykonuje wq (write and quit)
  • g/match/d - Ex komenda do usuwania linii o podanym match, 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.

 26
Author: kenorb,
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.

 13
Author: Aniket Sinha,
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

Aby uzyskać wynik inplace like z grep możesz to zrobić:

echo "$(grep -v "pattern" filename)" >filename
 12
Author: Jahid,
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

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
 10
Author: Jadzia,
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
 8
Author: Oleg Mazko,
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

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).

 7
Author: Bhuvanesh,
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

echo -e "/thing_to_delete\ndd\033:x\n" | vim file_to_edit.txt

 2
Author: Shizzmo,
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
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).

 2
Author: Kjetil S.,
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
cat filename | grep -v "pattern" > filename.1
mv filename.1 filename
 0
Author: Andrey Izman,
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

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
 0
Author: FatihSarigol,
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