2つのechoコマンドの出力の間に\ nを削除する方法は?

2つのechoコマンドの出力の間に\ nを削除する方法は?

各行にファイル名を含むテキストファイルがあります。

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 -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(スクリプトのshebangに示すように)を使用しているので、この-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

関連情報