Hoe te verwijderen uit een tekstbestand, alle regels die een specifieke reeks bevatten?

Hoe zou ik SED gebruiken om alle regels in een tekstbestand te verwijderen dat een specifieke reeks bevat?


Antwoord 1, Autoriteit 100%

Om de regel te verwijderen en de uitvoer af te drukken naar Standard OUT:

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

Om het bestand rechtstreeks aan te passen – werkt niet met BSD SED:

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

hetzelfde, maar voor BSD SED (Mac OS X en FreeBSD) – werkt niet met GNU SED:

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

Om het bestand rechtstreeks aan te passen (en een back-up maken) – werkt met BSD en GNU SED:

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

Antwoord 2, Autoriteit 22%

Er zijn vele andere manieren om lijnen met specifieke reeks te verwijderen, behalve sed:

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 en hoger)

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

En natuurlijk sed(het afdrukken van de inverse is sneller dan de werkelijke schrapping):

sed -n '/pattern/!p' file

Antwoord 3, Autoriteit 9%

U kunt gebruik maken van sed om lijnen in de plaats te vervangen in een bestand. Echter, het lijkt te zijn veel trager dan het gebruik van grep voor de inverse in een tweede bestand en vervolgens het verplaatsen van het tweede bestand over het origineel.

b.g

sed -i '/pattern/d' filename      

of

grep -v "pattern" filename > filename2; mv filename2 filename

Het eerste commando duurt 3 keer langer op mijn machine toch.


Antwoord 4, Autoriteit 3%

De eenvoudige manier om het te doen, met GNU sed

sed --in-place '/some string here/d' yourfile

Antwoord 5

U kunt overwegen om met behulp van ex(dat is een standaard Unix command-based editor):

ex +g/match/d -cwq file

waarbij:

  • +uitvoert gegeven Ex-commando (man ex), hetzelfde als -c, die uitvoert wq(write en af ​​te sluiten)
  • g/match/d– Ex opdracht te wissen lijnen met opgegeven matchZie: Power of g

Het bovenstaande voorbeeld is een POSIX-compatibele methode voor het ter plaatse bewerken van een bestand volgens deze post op Unix.SEen POSIX-specificaties voor ex.


Het verschil met sedis dat:

sedis een Stream EDitor, geen bestandseditor.BashFAQ

Tenzij je geniet van niet-draagbare code, I/O-overhead en andere vervelende neveneffecten. Dus in feite zijn sommige parameters (zoals in-place/-i) niet-standaard FreeBSD-extensies en zijn mogelijk niet beschikbaar op andere besturingssystemen.


Antwoord 6

Ik worstelde hiermee op Mac. Bovendien moest ik het doen met variabele vervanging.

Dus ik gebruikte:

sed -i '' "/$pattern/d" $file

waarbij $filehet bestand is waar verwijdering nodig is en $patternhet patroon is dat moet worden vergeleken voor verwijdering.

Ik heb de ''gekozen uit deze commentaar.

Het ding om op te merken hier is het gebruik van dubbele aanhalingstekensin "/$pattern/d". Variabele werkt niet als we enkele aanhalingstekens gebruiken.


Antwoord 7

Je kunt dit ook gebruiken:

grep -v 'pattern' filename

Hier wordt -valleen anders afgedrukt dan uw patroon (dat betekent match omkeren).


Antwoord 8

Ik heb een kleine benchmark gemaakt met een bestand dat ongeveer 345.000 regels bevat. De manier met greplijkt in dit geval ongeveer 15 keer sneller te zijn dan de sed-methode.

Ik heb zowel met als zonder de instelling LC_ALL=C geprobeerd, het lijkt erop dat de timing niet significant verandert. De zoekreeks (CDGA_00004.pdbqt.gz.tar) bevindt zich ergens in het midden van het bestand.

Hier zijn de commando’s en de timing:

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

Antwoord 9

Om een vergelijkbaar resultaat te krijgen met grepkun je dit doen:

echo "$(grep -v "pattern" filename)" >filename

Antwoord 10

SED:

AWK:

GREP:


Antwoord 11

perl -i    -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3

Het eerste commando bewerkt het/de bestand(en) inplace (-i).

Het tweede commando doet hetzelfde, maar bewaart een kopie of back-up van de originele bestanden door .bk toe te voegen aan de bestandsnamen (.bk kan in alles worden gewijzigd).


Antwoord 12

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


Antwoord 13

cat filename | grep -v "pattern" > filename.1
mv filename.1 filename

Antwoord 14

Voor het geval iemand het wil doen voor exacte overeenkomsten van strings, kun je de -wvlag in grep – w gebruiken voor geheel. Dat wil zeggen, als u bijvoorbeeld de regels met nummer 11 wilt verwijderen, maar de regels met nummer 111 wilt behouden:

-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

Het werkt ook met de vlag -fals u meerdere exacte patronen tegelijk wilt uitsluiten. Als “zwarte lijst” een bestand is met meerdere patronen op elke regel die u uit “bestand” wilt verwijderen:

grep -w -v -f blacklist file

Antwoord 15

U kunt ook een reeks regels in een bestand verwijderen.
Bijvoorbeeld om opgeslagen procedures in een SQL-bestand te verwijderen.

sed '/CREATE PROCEDURE.*/,/END ;/d' sqllines.sql

Hiermee worden alle regels tussen CREATE PROCEDURE en END ; verwijderd.

Ik heb veel sql-bestanden opgeschoond met dit sed-commando.


Antwoord 16

om de behandelde tekst in de console weer te geven

cat filename | sed '/text to remove/d' 

om behandelde tekst in een bestand op te slaan

cat filename | sed '/text to remove/d' > newfile

om behandelde tekstinfo toe te voegen aan een bestaand bestand

cat filename | sed '/text to remove/d' >> newfile

om reeds behandelde tekst te behandelen, verwijder in dit geval meer regels van wat is verwijderd

cat filename | sed '/text to remove/d' | sed '/remove this too/d' | more

de | morezal tekst in blokken van één pagina tegelijk weergeven.


Antwoord 17

Je kunt de goede oude edgebruiken om een bestand op een vergelijkbare manier te bewerken als het antwoorddie exgebruikt. Het grote verschil in dit geval is dat edzijn commando’s via standaardinvoer opneemt, niet zoals commandoregelargumenten zoals exdat kunnen. Als je het in een script gebruikt, is de gebruikelijke manier om dit te accommoderen door printfte gebruiken om er commando’s naar toe te leiden:

printf "%s\n" "g/pattern/d" w | ed -s filename

of met een heredoc:

ed -s filename <<EOF
g/pattern/d
w
EOF

Antwoord 18

Vreemd genoeg geeft het geaccepteerde antwoord eigenlijk geen direct antwoord op de vraag. De vraag gaat over het gebruik van sed om een stringte vervangen, maar het antwoord lijkt kennis te veronderstellen van hoe een willekeurige string in een regexkan worden omgezet.

Veel programmeertaalbibliotheken hebben een functie om een dergelijke transformatie uit te voeren, bijvoorbeeld

python: re.escape(STRING)
ruby: Regexp.escape(STRING)
java:  Pattern.quote(STRING)

Maar hoe doe je dat op de opdrachtregel?

Aangezien dit een sed-georiënteerde vraag is, zou een benadering zijn om sed zelf te gebruiken:

sed 's/\([\[/({.*+^$?]\)/\\\1/g'

Dus gegeven een willekeurige string $STRING zouden we zoiets kunnen schrijven als:

re=$(sed 's/\([\[({.*+^$?]\)/\\\1/g' <<< "$STRING")
sed "/$re/d" FILE

of als oneliner:

sed "/$(sed 's/\([\[/({.*+^$?]\)/\\\1/g' <<< "$STRING")/d" 

met variaties zoals elders op deze pagina beschreven.


Antwoord 19

Verwijder regels uit alle bestanden die overeenkomen met de overeenkomst

grep -rl 'text_to_search' . | xargs sed -i '/text_to_search/d'

Other episodes