Fügen Sie am Anfang jeder Zeile eine Präfixzeichenfolge hinzu


333

Ich habe eine Datei wie folgt:

line1
line2
line3

Und ich möchte bekommen:

prefixline1
prefixline2
prefixline3

Ich könnte ein Ruby-Skript schreiben, aber es ist besser, wenn ich es nicht brauche.

prefixwird enthalten /. Es ist /opt/workdir/zum Beispiel ein Weg .

Antworten:


525
# If you want to edit the file in-place
sed -i -e 's/^/prefix/' file

# If you want to create a new file
sed -e 's/^/prefix/' file > file.new

Wenn es prefixenthält /, können Sie jedes andere Zeichen verwenden, das sich nicht in befindet prefix, oder dem entkommen /, sodass der sedBefehl wird

's#^#/opt/workdir#'
# or
's/^/\/opt\/workdir/'

1
@benjamin, ich hatte Ihre Antwort bereits positiv bewertet, bevorzuge jedoch sedleichte Aufgaben wie diese. Wenn "Präfix" bekannt ist, ist es sehr einfach, ein Zeichen auszuwählen, das nicht aus "Präfix" stammt.
Alok Singhal

1
Vergessen Sie nicht, dass Sie auch sedin einer Pipeline verwenden können, z foo | sed -e 's/^/x /' | bar.
Zigg

1
@Dataman cool. Ein anderer Weg wäre sed -e '2,$s/^/prefix/'.
Alok Singhal

1
@ BinChen entkommen /dergleichen \/(in Zeichenfolgen in einfachen Anführungszeichen) oder \\/(in Zeichenfolgen in doppelten Anführungszeichen)

8
Verwenden sed -e 's/$/postfix/' fileSie diese Option, wenn Sie am Ende jeder Zeile eine Zeichenfolge hinzufügen möchten.
Brian

121
awk '$0="prefix"$0' file > new_file

Mit Perl (Ersatz an Ort und Stelle):

perl -pi 's/^/prefix/' file

8
Mit einer Pipe / einem Stream oder einer Variablen:prtinf "$VARIABLE\n" | awk '$0="prefix"$0'
ThorSummoner

2
Mit einer großen Datei (12 G) wird awkberichtet awk: out of memory in readrec 1 source line number 1, aber die Lösung mit sederfolgreich abgeschlossen.
jrm

33

Sie können Vim im Ex-Modus verwenden:

ex -sc '%s/^/prefix/|x' file
  1. % Wählen Sie alle Zeilen aus

  2. s ersetzen

  3. x speichern und schließen


1
Für mich öffne ich die Datei nur in vim und tippe :%s/^/prefix/, da diese Strategie in vielen Situationen nützlich ist
Frank Bryce

23

Wenn Ihr Präfix etwas kompliziert ist, geben Sie es einfach in eine Variable ein:

prefix=path/to/file/

Dann übergeben Sie diese Variable und lassen awk damit umgehen:

awk -v prefix="$prefix" '{print prefix $0}' input_file.txt


6

Verwenden der Shell:

#!/bin/bash
prefix="something"
file="file"
while read -r line
do
 echo "${prefix}$line"
done <$file > newfile
mv newfile $file

5

Hier ist eine gut lesbare Oneliner-Lösung mit dem tsBefehl von moreutils

$ cat file | ts prefix | tr -d ' '

Und wie es Schritt für Schritt abgeleitet wird:

# Step 0. create the file

$ cat file
line1
line2
line3
# Step 1. add prefix to the beginning of each line

$ cat file | ts prefix
prefix line1
prefix line2
prefix line3
# Step 2. remove spaces in the middle

$ cat file | ts prefix | tr -d ' '
prefixline1
prefixline2
prefixline3

'ts' ist in vielen Linux-Distributionen nicht standardmäßig installiert. Beim Downvoting, da das nachfolgende "tr -d ''" in dieser Antwort alle Leerzeichen aus den Zeilen entfernt, nicht nur das Leerzeichen, das von 'ts' hinzugefügt wurde
Tim Bird,

3

Obwohl ich nicht glaube, dass pierr dieses Problem hatte, brauchte ich eine Lösung, die die Ausgabe vom Live- "Tail" einer Datei nicht verzögert, da ich mehrere Warnprotokolle gleichzeitig überwachen und jeder Zeile den Namen des jeweiligen Protokolls voranstellen wollte .

Leider haben sed, cut usw. zu viel Pufferung eingeführt und mich davon abgehalten, die aktuellsten Zeilen zu sehen. Steven Pennys Vorschlag, die -sOption von zu verwenden, nlwar faszinierend, und Tests haben gezeigt, dass die unerwünschte Pufferung, die mich beschäftigte, nicht eingeführt wurde.

Es gab jedoch einige Probleme bei der Verwendung nl, die mit dem Wunsch zusammenhängen, die unerwünschten Zeilennummern zu entfernen (selbst wenn Sie sich nicht für die Ästhetik interessieren, kann es Fälle geben, in denen die Verwendung der zusätzlichen Spalten unerwünscht wäre). Erstens führt die Verwendung von "Ausschneiden" zum Entfernen der Zahlen das Pufferproblem erneut ein, sodass die Lösung zerstört wird. Zweitens hilft die Verwendung von "-w1" nicht, da dies die Zeilennummer NICHT auf eine einzelne Spalte beschränkt - sie wird nur breiter, wenn mehr Ziffern benötigt werden.

Es ist nicht schön, wenn Sie dies an anderer Stelle erfassen möchten, aber da ich genau das nicht tun musste (alles wurde bereits in Protokolldateien geschrieben, ich wollte nur mehrere gleichzeitig in Echtzeit ansehen), das Beste Um die Zeilennummern zu verlieren und nur mein Präfix zu haben, begann der -sString mit einem Wagenrücklauf (CR oder ^ M oder Strg-M). Also zum Beispiel:

#!/bin/ksh

# Monitor the widget, framas, and dweezil
# log files until the operator hits <enter>
# to end monitoring.

PGRP=$$

for LOGFILE in widget framas dweezil
do
(
    tail -f $LOGFILE 2>&1 |
    nl -s"^M${LOGFILE}>  "
) &
sleep 1
done

read KILLEM

kill -- -${PGRP}

1
Verwenden Sie die -uOption zum Sedieren, um die Pufferung zu vermeiden.
Bryan Larsen

2
Die Pufferung kann mit unbuffer / stdbuf deaktiviert werden, siehe unix.stackexchange.com/q/25372/6205
myroslav

2

Verwenden von ed:

ed infile <<'EOE'
,s/^/prefix/
wq
EOE

Dies ersetzt für jede Zeile ( ,) den Anfang der Zeile ( ^) durch prefix. wqspeichert und beendet.

Wenn die Ersatzzeichenfolge einen Schrägstrich enthält, können wir sstattdessen ein anderes Trennzeichen verwenden für :

ed infile <<'EOE'
,s#^#/opt/workdir/#
wq
EOE

Ich habe das Here-Doc-Trennzeichen EOE("end of ed") zitiert , um eine Parametererweiterung zu verhindern. In diesem Beispiel würde es auch ohne Anführungszeichen funktionieren, aber es wird empfohlen, Überraschungen zu vermeiden, wenn Sie jemals eine $in Ihrem ed-Skript haben.


2

Verwenden von & (der gesamte Teil der Eingabe, der mit dem Muster übereinstimmt ”):

cat in.txt | sed -e "s/.*/prefix&/" > out.txt

ODER mit Rückverweisen:

cat in.txt | sed -e "s/\(.*\)/prefix\1/" > out.txt

2
  1. Sie können dies auch mit der Rückreferenztechnik erreichen

    sed -i.bak 's/\(.*\)/prefix\1/' foo.txt
    
  2. Sie können auch mit awk wie diesem verwenden

    awk '{print "prefix"$0}' foo.txt > tmp && mv tmp foo.txt
    

1

Hier ist ein abgeschlossenes Beispiel, das den sedAnsatz dieser Antwort verwendet :

$ cat /path/to/some/file | prefix_lines "WOW: "

WOW: some text
WOW: another line
WOW: more text

prefix_lines

function show_help()
{
  IT=$(CAT <<EOF
    Usage: PREFIX {FILE}

    e.g.

    cat /path/to/file | prefix_lines "WOW: "

      WOW: some text
      WOW: another line
      WOW: more text
  )
  echo "$IT"
  exit
}

# Require a prefix
if [ -z "$1" ]
then
  show_help
fi

# Check if input is from stdin or a file
FILE=$2
if [ -z "$2" ]
then
  # If no stdin exists
  if [ -t 0 ]; then
    show_help
  fi
  FILE=/dev/stdin
fi

# Now prefix the output
PREFIX=$1
sed -e "s/^/$PREFIX/" $FILE

2
Dies funktioniert nicht, wenn es PREFIXspezielle Zeichen für sed wie einen Schrägstrich enthält.
Josch

Guter Punkt ... Wenn Sie feststellen, dass Sie häufig Schrägstriche verwenden, können Sie mit dem sed-Teil ein anderes Trennzeichen verwenden, wie hier beschrieben , damit Sie es bei Suchvorgängen verwenden können. Andere spezielle Zeichen können durch Flucht mit einem Schrägstrich eingefügt werden, z. B.prefix_lines \*
Brad Parks

0

Für Leute auf BSD / OSX-Systemen gibt es ein Hilfsprogramm lam, kurz für Laminat. lam -s prefix filewird tun was du willst. Ich benutze es in Pipelines, zB:

find -type f -exec lam -s "{}: " "{}" \; | fzf

... die alle Dateien finden, jede auf ihnen ausführen und jeder Datei ein Präfix mit einem eigenen Dateinamen geben. (Und pumpen Sie den Ausgang zur Suche nach fzf.)


Ich bin auf Ubuntu 19.10 und es gibt keinen solchen Befehl
nafg

Sie haben Recht, es scheint, dass dies nur ein BSD-Befehl ist. POSIX hat es durch Einfügen ersetzt, aber Einfügen bietet nicht die Möglichkeit, eine vollständige Trennzeichenfolge hinzuzufügen. Ich werde meine Antwort aktualisieren.
Ray
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.