Vraag Zoek en vervang tekst in een bestand met behulp van opdrachten


Hoe kan ik specifieke woorden in een tekstbestand vinden en vervangen met behulp van de opdrachtregel?


434
2018-01-07 04:10


oorsprong


Moge van je interesse github.com/lucio-martinez/rch :-) - Lucio


antwoorden:


sed -i 's/original/new/g' file.txt

Uitleg:

  • sed = Stream EDitor
  • -i = op de plaats (d.w.z. terugzetten naar het originele bestand)
  • De opdrachtstring:

    • s = het vervangende commando
    • original = een reguliere expressie die het te vervangen woord beschrijft (of alleen het woord zelf)
    • new = de tekst om het te vervangen
    • g = globaal (d.w.z. vervang alles en niet alleen het eerste exemplaar)
  • file.txt = de bestandsnaam


724
2018-01-07 04:23



@mcExchange Als het specifiek de / teken dat u moet matchen, u kunt gewoon een ander teken gebruiken als scheidingsteken (bijv. 's_old/text_new/text_g'). Anders kun je een \  vóór een van $ * . [ \ ^ om het letterlijke karakter te krijgen. - cscarney
@BrianZ Wat het bestandssysteem betreft, is de uitvoer van sed een nieuw bestand met dezelfde naam. Het is een van de vaak gerapporteerde bugs die geen bugs zijn - cscarney
Je wilt misschien s/\boriginal\b/new/g in plaats van s/original/new/g (\b komt overeen met een woordgrens) om alleen hele woorden te vervangen. - Chris Martin
De OSX-opdracht sed -i '.bak' 's/original/new/g' file.txt kan ook worden uitgevoerd met een verlenging met een lengte van nul sed -i '' 's/original/new/g' file.txt, die geen back-up zal genereren. - Kirk
MacOS-gebruikers moeten '' "achter -i als een parameter voor -i toevoegen ed.gs/2016/01/26/os-x-sed-invalid-command-code zodat het bestand wordt overschreven. - geoyws


Er zijn een aantal verschillende manieren om dit te doen. Eén gebruikt sed en Regex. SED is een Streameditor voor het filteren en transformeren van tekst. Een voorbeeld is als volgt:

marco@imacs-suck: ~$ echo "The slow brown unicorn jumped over the hyper sleeping dog" > orly
marco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarly
marco@imacs-suck: ~$ cat yarly
The quick brown unicorn jumped over the hyper sleeping dog

Een andere manier die meer steek houdt dan < strin en > strout is met pijpen!

marco@imacs-suck: ~$ cat yarly | sed s/unicorn/fox/ | sed s/hyper/lazy/ > nowai
marco@imacs-suck: ~$ cat nowai 
The quick brown fox jumped over the lazy sleeping dog

26
2018-01-07 04:26



merk op cat in cat file | sed '...' is onnodig. Je kunt het direct zeggen sed '...' file. - fedorqui
Inderdaad kan dit verder worden verminderd: sed -i'.bak' -e 's/unicorn/fox/g;s/hyper/brown/g' yarly zal het bestand elk jaar nemen en de 2 veranderingen op zijn plaats doen tijdens het maken van een back-up. Gebruik makend van time bash -c "$COMMAND" tot tijd suggereert het dat deze versie een ~ 5 keer sneller is. - pbhj


U kunt Vim in Ex-modus gebruiken:

ex -sc '%s/OLD/NEW/g|x' file
  1. % selecteer alle lijnen

  2. s plaatsvervanger

  3. g vervang alle exemplaren in elke regel

  4. x schrijf als er wijzigingen zijn aangebracht (ze hebben) en ga uit


15
2018-04-16 18:36





Via het gsub-commando van awk,

awk '{gsub(/pattern/,"replacement")}' file

Voorbeeld:

awk '{gsub(/1/,"0");}' file

In het bovenstaande voorbeeld worden alle 1's vervangen door 0's, ongeacht de kolom waar deze zich bevond.


Als je een vervanging op een specifieke kolom wilt doen, doe dat dan als volgt,

awk '{gsub(/pattern/,"replacement",column_number)}' file

Voorbeeld:

awk '{gsub(/1/,"0",$1);}' file

Het vervangt alleen 1 door 0 in kolom 1.

Via Perl,

$ echo 'foo' | perl -pe 's/foo/bar/g'
bar

14
2017-07-02 12:59



Ik gebruikte dit op de MacOS-terminal en het deed niets ... - Jim


Er zijn veel verschillende manieren om dit te bereiken. Afhankelijk van de complexiteit van wat men probeert te bereiken met het vervangen van een string en afhankelijk van tools waarmee de gebruiker vertrouwd is, kunnen sommige methoden de voorkeur hebben boven andere.

In dit antwoord gebruik ik eenvoudig input.txt bestand, dat u kunt gebruiken om alle hier gegeven voorbeelden te testen. De inhoud van het bestand:

roses are red , violets are blue
This is an input.txt and this doesn't rhyme

BASH

Bash is niet echt bedoeld voor tekstverwerking, maar eenvoudige vervangingen kunnen via worden gedaan parameteruitbreiding , in het bijzonder hier kunnen we een eenvoudige structuur gebruiken ${parameter/old_string/new_string}.

#!/bin/bash
while IFS= read -r line
do
    case "$line" in
       *blue*) printf "%s\n" "${line/blue/azure}" ;;
       *) printf "%s\n" "$line" ;;
    esac
done < input.txt

Dit kleine script vervangt niet op de plaats, wat betekent dat u nieuwe tekst in een nieuw bestand moet opslaan en het oude bestand moet verwijderen, of mv new.txt old.txt

Kanttekening: als je nieuwsgierig bent naar het waarom while IFS= read -r ; do ... done < input.txt wordt gebruikt, het is in feite shell's manier om regel voor regel te lezen. Zien deze als referentie.

AWK

AWK, dat een hulpprogramma voor tekstverwerking is, is redelijk geschikt voor een dergelijke taak. Het kan eenvoudige vervangingen doen en nog veel meer geavanceerde op basis van normale uitdrukkingen. Het biedt twee functies: sub() en gsub(). De eerste vervangt alleen de eerste occurrence, terwijl de tweede - vervangt occurrences in hele reeks. Als we bijvoorbeeld een string hebben one potato two potato , dit zou het resultaat zijn:

$ echo "one potato two potato" | awk '{gsub(/potato/,"banana")}1'
one banana two banana

$ echo "one potato two potato" | awk '{sub(/potato/,"banana")}1'                                      
one banana two potato 

AWK kan een invoerbestand als argument meenemen, dus hetzelfde doen met input.txt , zou gemakkelijk zijn:

awk '{sub(/blue/,"azure")}1' input.txt

Afhankelijk van de versie van AWK die u hebt, kan deze al dan niet ter plaatse worden bewerkt, daarom is de gebruikelijke praktijk opslaan en vervangen van nieuwe tekst. Bijvoorbeeld zoiets als dit:

awk '{sub(/blue/,"azure")}1' input.txt > temp.txt && mv temp.txt input.txt

SED

Sed is een regeleditor. Het maakt ook gebruik van reguliere expressies, maar voor eenvoudige vervangingen volstaat het om te doen:

sed 's/blue/azure/' input.txt

Wat goed is aan deze tool is dat deze in-place editing heeft, waarmee je kunt inschakelen -i vlag.

Perl

Perl is een andere tool die vaak wordt gebruikt voor tekstverwerking, maar het is een taal voor algemene doeleinden en wordt gebruikt in netwerken, systeembeheer, desktop-apps en vele andere plaatsen. Het leende veel concepten / functies uit andere talen zoals C, sed, awk en anderen. Eenvoudige vervanging kan als volgt worden gedaan:

perl -pe 's/blue/azure/' input.txt

Net als sed heeft perl ook de vlag -i.

Python

Deze taal is zeer veelzijdig en wordt ook gebruikt in een groot aantal verschillende toepassingen. Het heeft veel functies voor het werken met strings, waaronder is replace(), dus als je een variabele hebt zoals var="Hello World" , Je zou kunnen doen var.replace("Hello","Good Morning")

De eenvoudige manier om het bestand te lezen en de tekenreeks daarin te vervangen zou als volgt zijn:

python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt

Met Python moet je echter ook naar een nieuw bestand uitvoeren, wat je ook vanuit het script zelf kunt doen. Hier is bijvoorbeeld een eenvoudige:

#!/usr/bin/env python
import sys
import os
import tempfile

tmp=tempfile.mkstemp()

with open(sys.argv[1]) as fd1, open(tmp[1],'w') as fd2:
    for line in fd1:
        line = line.replace('blue','azure')
        fd2.write(line)

os.rename(tmp[1],sys.argv[1])

Dit script moet worden gebeld input.txt als opdrachtregelargument.

Python kan ook reguliere expressies hebben, met name er is re module, die heeft re.sub() functie, die kan worden gebruikt voor meer geavanceerde vervangingen.


12
2018-02-03 07:49





sed is de stream editor, daar kun je gebruik van maken | (pijp) om te verzenden standaard streams (STDIN en STDOUT specifiek) door sed en ze programmatisch on the fly aanpassen, waardoor het een handig hulpmiddel is in de Unix-filosofietraditie; maar kan ook rechtstreeks bestanden bewerken met behulp van de -i parameter hieronder vermeld.
Stel je de volgende situatie voor:

sed -i -e 's/few/asd/g' hello.txt

s/ is gewend aan sde gevonden uitdrukking few met asd:

De weinigen, de dapperen.


De Asd, de dapperen.

/g staat voor "global", wat betekent dit voor de hele regel. Als je de /g (met s/few/asd/er moeten altijd drie schuine strepen zijn, wat er ook gebeurt) en few verschijnt tweemaal op dezelfde regel, alleen de eerste few is veranderd in asd:

De weinige mannen, de weinige vrouwen, de dapperen.


De asd-mannen, de weinige vrouwen, de dapperen.

Dit is onder bepaalde omstandigheden nuttig, zoals het wijzigen van speciale tekens aan het begin van regels (bijvoorbeeld het vervangen van de meer dan-symbolen die sommige mensen gebruiken om eerder materiaal in e-mailthreads aan te halen met een horizontaal tabblad, terwijl een geciteerde algebraïsche ongelijkheid later in de regel wordt weergegeven onaangeroerd), maar in je voorbeeld waar je dat opgeeft overal  few komt het moet worden vervangen, zorg ervoor dat je dat hebt /g.

De volgende twee opties (vlaggen) worden gecombineerd tot één, -ie:

-i optie wordt gebruikt om te bewerken ikn plaats op het bestand hello.txt.

-e optie geeft de expression / opdracht uit te voeren, in dit geval s/.

Opmerking: het is belangrijk dat u dit gebruikt -i -e zoeken / vervangen. Als je dat doet -ie, u maakt een back-up van elk bestand met de letter 'e' als bijlage.


6
2017-11-23 09:00





Je kunt dit als volgt doen:

locate <part of filaname to locate> | xargs sed -i -e "s/<Old text>/<new text>/g" 

Voorbeelden: vervang alle occurrences [logdir ',' '] (zonder []) door [logdir', os.getcwd ()] in alle bestanden die het resultaat zijn van de locate-opdracht, doe:

locate tensorboard/program.py | xargs sed -i -e "s/logdir', ''/logdir', os.getcwd()/g"

waar [tensorboard / program.py] bestand is om te zoeken


0
2017-07-24 02:13



Hoi. Uw keuze van strings (logdir', '' -> /logdir', os.getcwd()) maakt dit antwoord moeilijk te ontleden. Het is ook de moeite waard om te specificeren dat je antwoord eerst de bestanden lokaliseert om sed op te gebruiken, omdat het geen deel uitmaakt van de vraag. - mwfearnley
Hallo, dit antwoord is zowel zoeken als vervangen als het <oude tekst> in het bestand heeft gevonden. - Nguyễn Tuấn Anh
Ik kies dit antwoord voor alles wat ze gebruiken tensorboard in keras, die het commando willen wijzigen van: tensorboard --logdir = '/ path / to / log / folder /' om te gebruiken: tensorboard alleen, wanneer je in de logs-map blijft. Het is erg handig - Nguyễn Tuấn Anh