Wie entferne ich \n zwischen den Ausgaben zweier Echo-Befehle?

Wie entferne ich \n zwischen den Ausgaben zweier Echo-Befehle?

Ich habe eine Textdatei, die in jeder Zeile einen Dateinamen enthält:

111_c4l5r120.png
123_c4l4r60.png
135_c4l4r180.png
147_c4l3r60.png
15_c4l1r120.png
...

Ich möchte es in diese Form umwandeln:

111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15
...

mit diesem Code:

#!/bin/bash
while IFS='' read -r line || [[  -n "$line"  ]]; do
   echo "$line" >> output.txt   
   echo "$line" | cut -d'_' -f 1 >> output.txt
done < "$1"

aber das Ergebnis ist:

111_c4l5r120.png 
111
123_c4l4r60.png 
123
135_c4l4r180.png 
135
147_c4l3r60.png 
147
15_c4l1r120.png 
15
...

Wie muss ich mein Skript ändern, um die gewünschte Ausgabe zu erhalten?

Antwort1

Machen Sie so etwas nicht in der Shell! Es ist viel komplexer als nötig, fehleranfällig und viel, viel langsamer. Es gibt viele Tools, die für solche Textmanipulationen entwickelt wurden. Zum Beispiel in sed(hier unter der Annahme aktueller GNU- oder BSD-Implementierungen für -E):

$ sed -E 's/([^_]*).*/& \1/' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15

Oder für alle sed:

$ sed 's/\([^_]*\).*/& \1/' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15

Perl:

$ perl -pe 's/(.+?)_.*/$& $1/' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15

awk:

$ awk -F_ '{print $0,$1}' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15

Antwort2

Sofern Sie hierfür nicht unbedingt die Shell verwenden müssen,Terdons Antwortbietet bessere Alternativen.

bashDa Sie (wie im Shebang des Skripts angegeben) verwenden , können Sie die -nOption zum Echo verwenden:

echo -n "${line} " >> output.txt
echo "$line" | cut -d'_' -f 1 >> output.txt

Oder Sie können Shell-Funktionen verwenden, um die Zeile ohne Folgendes zu verarbeiten cut:

echo "${line} ${line%%_*}" >> output.txt

(beide echoZeilen ersetzen).

Alternativ printfwürde es auch funktionieren, funktioniert in jedemPOSIX-Shellund ist im Allgemeinen besser (sieheWarum ist printf besser als echo?für Details):

printf "%s " "${line}" >> output.txt
echo "$line" | cut -d'_' -f 1 >> output.txt

oder

printf "%s %s\n" "${line}" "${line%%_*}" >> output.txt

(Genau genommen, im Klartext /bin/sh,echo -nist nicht tragbar. Da Sie bashes explizit verwenden, ist es hier in Ordnung.)

Antwort3

Hier sind Sie ja:

#!/bin/bash

while IFS='' read -r line || [[  -n "$line"  ]]; do
   echo "$line" `echo "$line" | cut -d'_' -f 1` >> output.txt
#   echo "$line" | cut -d'_' -f 1 >> output.txt
done < "$1"

Ausgabe:

$ rm -rf output.txt
$ ./test.sh 1.1; cat output.txt
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15

verwandte Informationen