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 uitvoertwq
(write en af te sluiten)g/match/d
– Ex opdracht te wissen lijnen met opgegevenmatch
Zie: 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 sed
is dat:
sed
is 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 $file
het bestand is waar verwijdering nodig is en $pattern
het 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 -v
alleen 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 grep
lijkt 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 grep
kun 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 -w
vlag 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 -f
als 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 | more
zal tekst in blokken van één pagina tegelijk weergeven.
Antwoord 17
Je kunt de goede oude ed
gebruiken om een bestand op een vergelijkbare manier te bewerken als het antwoorddie ex
gebruikt. Het grote verschil in dit geval is dat ed
zijn commando’s via standaardinvoer opneemt, niet zoals commandoregelargumenten zoals ex
dat kunnen. Als je het in een script gebruikt, is de gebruikelijke manier om dit te accommoderen door printf
te 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'