두 개의 echo 명령 출력에서 ​​\ n을 제거하는 방법은 무엇입니까?


13

각 줄에 하나의 파일 이름을 포함하는 텍스트 파일이 있습니다.

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
...

원하는 출력을 갖도록 스크립트를 어떻게 변경해야합니까?


Google은 더 나은 결과를 찾습니다 (예 : this) .
Thomas Dickey

답변:


17

이를 위해 쉘을 사용해야 할 필요가 없다면 terdon의 대답 은 더 나은 대안을 제공합니다.

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/sh, echo -n이식 할 수 없습니다 . 당신이 명시 적으로 사용하고 있기 때문에 bash여기의 확인을.)


의견은 긴 토론을위한 것이 아닙니다. 이 대화는 채팅 으로 이동 되었습니다 .
terdon

23

껍질에 이런 종류의 일을하지 마십시오! 필요한 것보다 훨씬 복잡하고 오류가 발생하기 쉽고 훨씬 늦습니다. 이러한 텍스트 조작을 위해 설계된 많은 도구가 있습니다. 예를 들어 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

1
그러나 외부 유틸리티는 그다지 좋지 않습니다.
EKons 2016 년

6
@ ΈρικΚωνσταντόπουλος 그렇습니다. 실제로 몇 배 더 빠릅니다. 껍질은 이런 종류의 일에별로 좋지 않습니다. 쉘의 주요 작업은 결국 외부 유틸리티를 시작하는 것입니다. OP의 접근 방식에 소요 된 시간과 여기에있는 모든 솔루션에 의해 취해진 시간을 비교하십시오. 쉘 루프는 매우 느립니다. 더 설득력이 필요하면 이것을 읽으십시오 .
terdon

휴대 성 측면에서 그렇습니다. 속도면에서 그렇습니다. 또한 @ StéphaneChazelas가 귀하의 별칭입니까?
EKons 2016 년

4
@ ΈρικΚωνσταντόπουλος Θα 'θελα :) 아니요, 그는 단지 두 개의 댓글 스레드와 관련된 2 개의 위대한 답변을 작성했습니다. 이식성에 관해서는 * nix 기계의 ~ 90 % 정도에서만 작동하는 펄 접근법을 제외하고는 (소수) 예외적으로, 3 가지 솔루션은 모두 휴대 가능하고 쉘에 구애받지 않습니다. 또는 추가 휴대 성 sedsed 's/\([^_]*\).*/& \1/' file위해 언제든지 사용할 수 있습니다. 포인트 당신은 믿을 수있다 awk그리고 sed더 당신이 다른 거의 아무것도 믿을 수있는 것보다 거기.
terdon

2

여기 있어요:

#!/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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.