Wie kann ich Muster in einer einzigen Zeile zusammenführen?

10

Ich mache grep und sed und erhalte 2 Zeilen einer Datei, die mich interessiert. Wie kann ich diese Zeilen in einer einzelnen Zeile erhalten, die mit dem neuen Zeilenzeichen endet?
Jetzt bekomme ich:

pattern1  
pattern2  

Ich hätte gern pattern1 pattern2 \n

Jim
quelle
1
Können Sie mehr Beispieldaten teilen?
slm
Verwenden Sie printf %s\\n pattern1 pattern2 | sed '$!N;s/\n/ /'
Valentin Bajrami
Einfügen ist das Werkzeug für den Job, wenn Sie mehrere Ausgabezeilen zu einer zusammenführen möchten.
slm
irgendein spezielles Werkzeug? Wie wollen Sie das machen?
Braiam

Antworten:

7

paste::

{...pipeline...} | paste -d " " - -

Das heißt: "Lies eine Zeile aus stdin (der ersten -), lies eine andere Zeile aus stdin (der zweiten -) und verbinde sie dann mit einem Leerzeichen."


eine Bash-spezifische Technik:

$ x=$(grep -o pattern. test.txt)
$ echo "$x"
pattern1
pattern2
$ mapfile -t <<< "$x"
$ echo "${MAPFILE[*]}"
pattern1 pattern2

Ref: http://www.gnu.org/software/bash/manual/bashref.html#index-mapfile

Glenn Jackman
quelle
Was ist - -? Ist der Befehl so?
Jim
@ Jim - ja das stimmt. Diese sagen, pastewie die Eingabe verarbeitet werden soll. 2 auf einmal. Fügen Sie mehr hinzu, um jeweils 3 zu tun. seq 10 | paste -d " " - - .
slm
6

Ich werde drei Versionen verschiedener Methoden hintereinander setzen

AWK

printf %s\\n pattern1 pattern2 | awk -vRS="\n" -vORS=" " '1; END {print RS}'

SED

printf %s\\n pattern1 pattern2 | sed '$!N;s/\n/ /'

TR

printf %s\\n pattern1 pattern2 | tr '\n' ' '; echo

Und es gibt noch viel mehr.

Valentin Bajrami
quelle
Die trLösung wird die Endung Newline schlucken, so dass Sie hinzufügen möchten ; echozu , dass man
glenn Jackman
@glennjackman ah richtig! Danke für den Tipp. Es steht Ihnen jedoch frei, die Antwort zu ändern. Ich habe das bisschen verpasst!
Valentin Bajrami
2

Sie können dies mit einem Shell-Skript oder in der Befehlszeile tun. Fügen Sie einfach die Ausgabe des Befehls in eine Variable ein und dann echo:

# x=$(grep -e "pattern1\|pattern2" test)
# printf '%s\n' "$x"
pattern1 pattern2
Nidal
quelle
Ohne Anführungszeichen unterliegt die Variable auch einer Dateinamenerweiterung. Wenn Sie also Glob-Zeichen (wie *oder ?) im Ergebnis haben, können sich die Werte ändern.
Glenn Jackman
@glennjackman, danke für die Erwähnung, wie können wir das beheben?
Nidal
@Networker mit nicht Backticks, sondern $().. und mit printfprintf '%s\n' "$x"
Valentin Bajrami
Ich würde erwarten, dass dadurch printf '%s\n' "$x"die "interne" Newline NICHT entfernt wird.
Glenn Jackman
2

Mit sedkönnen Sie dies tun:

<your previous commands> | sed '{N; s/\n/ /}'
  • N;weist sedan, die nächste Zeile in den Musterbereich einzufügen, sodass jetzt sedmit beiden Zeilen gearbeitet wird.
  • s/\n/ / Ersetzt das Zeilenumbruchzeichen durch ein Leerzeichen und "verschmilzt" die beiden Zeilen miteinander.
Alaa Ali
quelle
2

Ein einfacher Weg, Pipe-Ausgabe an xargs:

$ echo -e 'a\nb' | xargs
a b

Dies funktioniert nur mit kleinen Ausgaben, da diese durch die maximale Anzahl von Zeichen pro Befehlszeile begrenzt sind. Der größte Wert hängt vom System ab. Sie können diesen Wert mit abrufen getconf ARG_MAX.

cuonglm
quelle
1
( set -f; IFS='
'; printf '%s %s\n' $(grepcmd <input)
) >output

IFS wird es gerne essen, wenn Sie wollen.

mikeserv
quelle
-1

Wickeln Sie Ihr Sed / Grep in Backticks

als Ihr ursprünglicher Befehl war:

grep -i 'foo' mylog.log | sed 's/bar/baz/gi'

Ihr neuer Befehl wäre:

`grep -i 'foo' mylog.log | sed 's/bar/baz/gi'`

Erhält nicht die Zwischenräume zwischen den Linien, aber Sie können immer ein anderes sed-Rohr anheften:

 | sed 's/$/ /'
TheRuss
quelle
1
Oh nein. Das wird ausführen den Ausgang des sed - Befehl.
Glenn Jackman