2017-09-15 4 views
5

Ich möchte ein Muster mit sed entfernen, nur bei zweitem Vorkommen. Hier ist, was ich will, entfernen Sie ein Muster, aber beim zweiten Auftreten.Sed ersetzen bei zweitem Vorkommen

Was im file.csv ist:

a,Name(null)abc.csv,c,d,Name(null)abc.csv,f 
a,Name(null)acb.csv,c,d,Name(null)acb.csv,f 
a,Name(null)cba.csv,c,d,Name(null)cba.csv,f 

Ausgang gesucht:

a,Name(null)abc.csv,c,d,Name,f 
a,Name(null)acb.csv,c,d,Name,f 
a,Name(null)cba.csv,c,d,Name,f 

Das ist, was ich versuchte:

sed -r 's/(\(null)\).*csv//' file.csv 

Das Problem hierbei ist, dass der Regex auch ist gierig, aber ich kann nicht aufhören. Ich habe auch versucht diese, das erste Vorkommen von „null“ zu überspringen:

sed -r '0,/null/! s/(\(null)\).*csv//' file.csv 

auch versucht, aber die gierigen regex ist nach wie vor das Problem.

sed -r 's/(\(null)\).*csv//2' file.csv 

Ich habe gelesen, dass ? kann die Regex „faul“ machen, aber ich kann es nicht Training machen.

sed -r 's/(\(null)\).*?csv//' file.csv 
+0

Wenn Sie 3 oder mehr '(null) 's haben und immer noch nur das 2. Vorkommen entfernen wollen, dann t hink es wäre einfacher mit Perl zu arbeiten, mit '. *?' statt '. *'. –

Antwort

1

Die robustere awk Lösung:

Erweiterte Beispieldatei input.csv:

12,Name(null)randomstuff.csv,2,3,Name(null)randomstuff.csv, false,Name(null)randomstuff.csv 
12,Name(null)AotherRandomStuff.csv,2,3,Name(null)AotherRandomStuff.csv, false,Name(null)randomstuff.csv 
12,Name(null)alphaNumRandom.csv,2,3,Name(null)alphaNumRandom.csv, false,Name(null)randomstuff.csv 

Der Job:

awk -F, '{ c=0; for(i=1;i<=NF;i++) if($i~/\(null\)/ && c++==1) sub(/\(null\).*/,"",$i) }1' OFS=',' input.csv 

Der Ausgang:

12,Name(null)randomstuff.csv,2,3,Name, false,Name(null)randomstuff.csv 
12,Name(null)AotherRandomStuff.csv,2,3,Name, false,Name(null)randomstuff.csv 
12,Name(null)alphaNumRandom.csv,2,3,Name, false,Name(null)randomstuff.csv 
+0

Großartig das funktioniert gut! Ich muss mehr über awk tool herausfinden! – BeGreen

4

sed eine einfache Möglichkeit bietet, die Übereinstimmung werden, um zu bestimmen ersetzt. Fügen Sie einfach die Zahl nach dem Trennzeichen

$ sed 's/(null)[^.]*\.csv//2' ip.csv 
a,Name(null)abc.csv,c,d,Name,f 
a,Name(null)acb.csv,c,d,Name,f 
a,Name(null)cba.csv,c,d,Name,f 

$ # or [^,] if there are no , within fields 
$ sed 's/(null)[^,]*//2' ip.csv 
a,Name(null)abc.csv,c,d,Name,f 
a,Name(null)acb.csv,c,d,Name,f 
a,Name(null)cba.csv,c,d,Name,f 

Auch keine Notwendigkeit () zu entkommen, wenn nicht erweiterte reguläre Ausdrücke

mit
+0

Ich habe es versucht, wenn Sie in meiner Post näher betrachten. Das Problem war der Greedy Regex. Ich musste '. *' Mit '[^,] *' wie in Ihrem Beispiel ändern. Vielen Dank. – BeGreen

+1

nun, ich habe nicht gemerkt, dass du '// 1' probiert hast (später bearbeitet mit' // 2') ... also warst du nur durch gieriges Problem auf ... einfach zu lösen in diesem Fall, wie es ist Workarounds mit '[^,]' oder '[^.]' ... für den generischen Fall benötigen Sie möglicherweise die richtigen CSV-Parser in Perl/Python/etc – Sundeep

+1

Sie haben Recht, ich könnte dies mit Pyexcel getan, die ich verwende mein Skript. Hab nicht darüber nachgedacht! – BeGreen

-1

Execute:

awk '{sub(/.null.....csv,f/,",f")}1' file 

Und sollte die Ausgabe sein:

a,Name(null)abc.csv,c,d,Name,f 
a,Name(null)acb.csv,c,d,Name,f 
a,Name(null)cba.csv,c,d,Name,f