Wie entferne ich drei aufeinander folgende Zeilenvorschübe in einer Makefile-Regel?

892
WilliamKF

Ich muss drei aufeinander folgende Zeilenumbrüche in einer Eingabedatei suchen und ersetzen und sie aus einer Ausgabedatei nach einer Makefile-Regel für Centos 4 filtern. Ich verwende GNU sed v4.1.2 und GNU make v3.82. Ich habe folgende Variationen ausprobiert, bis jetzt ohne Erfolg:

THREE_LINE_FEEDS := $(shell echo "\012\012\012")  SED_RULE := 's/'$(THREE_LINE_FEEDS)'//'  output.txt: input.txt sed -r $(SED_RULE) input.txt > output.txt 

Mit dem vorgeschlagenen Perl bekomme ich dieses Problem in der Shell (angepasst an meine make-Regel):

> cat input.txt | perl -e '$/ = undef; _ = <>; s/\n//g; print;' > output.txt Can't modify constant item in scalar assignment at -e line 1, near "<>;" Execution of -e aborted due to compilation errors. 
2

2 Antworten auf die Frage

3
Thor

sedEs wird jeweils nur eine Zeile angezeigt, sodass die Suche nach aufeinander folgenden Zeilenvorschüben nicht funktioniert. Eine Möglichkeit ist, alle Daten in den Speicherplatz zu schieben und dann zu ersetzen, wenn alle Eingaben gesammelt wurden, z.

sed -r -n ' $! { # When it is not the last line 1 { h } # Replace hold space with first line 1! { H } # Otherwise append to hold space } $ { # When last line reached H # Append it to hold space g # Replace pattern space with hold space s/\n//g # Remove all occurrences of \n p # Print pattern space } ' input.txt 

Hier ist eine einfachere Option mit perl, funktioniert aber auf dieselbe Weise:

perl -e ' $/ = undef; # Slurp mode, read whole file $_ = <>; # Read file to $_ s/\n//g; # Remove all occurrences of \n print; # Output $_ ' input.txt 

Bearbeiten

Eine kürzere perlVersion von Peter O vorgeschlagen:

perl -0777 -pe 's/\n//g' input.txt 
  • -0777 aktiviert den Slurp-Modus.
  • -p Ergebnis wird implizit gedruckt.
Das Perl funktioniert nicht, wenn es in meine Makefile-Regeln eingefügt wird. Siehe oben aktualisierte Frage. WilliamKF vor 12 Jahren 0
Bei der Verwendung von "$" in Makefiles müssen sie geschützt werden. Fügen Sie dort ein zusätzliches "$" hinzu, also "perl -e" $$ / = undef; $$ _ = <>; s / \ n // g; print "input.txt> output.txt" sollte funktionieren. Thor vor 12 Jahren 0
Ja, hatte das herausgefunden, aber immer noch nicht funktioniert. Fehler beim Abrufen: Konstantes Element kann nicht in der Skalarzuweisung in -e Zeile 1 in der Nähe von "<>;" Ausführung von -e aufgrund von Übersetzungsfehlern abgebrochen. Kannst du in Perl pfeifen? Warum führt es -e aus? WilliamKF vor 12 Jahren 0
Der Fehler, den Sie erhalten, kommt von diesem Bit: `_ = <>;`, sollte `$ _ = <>;` sein. Entweder "perl -e ... infile" oder "cat infile |." perl -e ... `funktioniert. "-e" gibt an, dass der Befehl "perl" ausgeführt werden soll, siehe "perlrun (1)". Thor vor 12 Jahren 0
Bingo, es funktioniert jetzt, brauchte andere $, die im Makefile verdoppelt wurden. WilliamKF vor 12 Jahren 0
`perl -0777pe 's / \ n // g'` ist genau das Gleiche. `0777` versetzt Perl in den Datei-Slurp-Modus und` p` macht eine Leseschleife, die druckt Peter.O vor 12 Jahren 2
Schön, ich wusste nicht über die `-0777-Option. Thor vor 12 Jahren 0
0
WilliamKF

Für Interessierte ist hier die eigentliche Makefile-Regel (Ich konnte die Zeilenumbrüche im Original nicht erstellen, daher habe ich die Dokumentation mit einem Kommentar versehen):

# 0777 - Enables slurp mode (i.e. $/ = undef; - Slurp mode, read whole file # $_ = <>; - Read file to $_) # s/\n//g; - Remove occurrences of \n # p - Implicitly print result (i.e. print; - Output $_) output.txt: input.txt $(SED) -r $(SED_RULE) input.txt | perl -0777 -pe 's/\n//g' > output.txt