2 つの echo コマンドの出力間の \n を削除するにはどうすればよいですか?

2 つの echo コマンドの出力間の \n を削除するにはどうすればよいですか?

各行に 1 つのファイル名が含まれるテキスト ファイルがあります。

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

これを次の形に変換します:

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

このコードを使用します:

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

しかし、結果は次のようになります。

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

希望する出力を得るにはスクリプトをどのように変更すればよいでしょうか?

答え1

シェルでこのような操作をしないでください。必要以上に複雑で、エラーが発生しやすく、非常に遅くなります。このようなテキスト操作用に設計されたツールは多数あります。たとえば、sed(ここでは の最近の GNU または BSD 実装を想定しています-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

または、任意の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 -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

答え2

シェルを使用する特別な理由がない限り、テルドンの答えより良い代替案を提供します。

bashスクリプトのシェバンに示されているように、次のように使用しているため、-nエコーするオプションを使用できます。

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

または、 を使用せずにシェルの機能を使用して行を処理することもできますcut

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

(両方のecho行を置き換えます)。

あるいは、printfこれも効果的です。POSIX シェル、そして一般的にはより良いです(なぜ printf は echo よりも優れているのでしょうか?詳細については):

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

または

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

(厳密に言えば、平易に言えば/bin/shecho -n持ち運びできない明示的に使用しているため、bashここでは問題ありません。

答え3

はい、どうぞ:

#!/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"

出力:

$ 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

関連情報