후행 줄 바꿈 문자가 내 명령 대체에서 어디로 갔습니까?


15

다음 코드는 상황을 가장 잘 설명합니다. 마지막 줄이 마지막 줄 바꿈 문자를 출력하지 않는 이유는 무엇입니까? 각 줄의 출력은 주석에 표시됩니다. 내가 사용 GNU의 bash는, 버전 4.1.5

     echo -n $'a\nb\n'                  | xxd -p  # 610a620a  
           x=$'a\nb\n'   ; echo -n "$x" | xxd -p  # 610a620a
     echo -ne "a\nb\n"                  | xxd -p  # 610a620a
x="$(echo -ne "a\nb\n")" ; echo -n "$x" | xxd -p  # 610a62

4
드물게 필요할 때에 대한 해결 방법 :tmp=$(somecommand; echo a); tmp=${tmp%a}
Gilles 'SO- 악의를 멈추십시오'


1
@Gilles : 위의 예를 다시 살펴보면 : tmp=$(somecommand; echo a)...이 점은 분명히 집으로 돌아 왔습니다 ... 예제를 볼 때까지 내 경향은 여전히 ​​사용되었을 것입니다 echo -n a. 그러나 물론! 이 -n때문에 명령을 대체하는 어떤 경우에 도입 된 후행 줄 바꿈을 제거합니다! ... 감사합니다 ...
Peter.O

답변:


18

명령 대체 함수 $()(및 백틱)는 특히 줄 바꿈 문자를 제거합니다. 이것은 문서화 된 동작 이며, 구문을 사용할 때 항상 알고 있어야합니다.

텍스트 본문 안의 줄 바꿈은 대체 연산자에 의해 제거되지 않지만 셸에서 단어 분할을 수행 할 때 제거 될 수도 있으므로 따옴표 사용 여부에 따라 다릅니다. 이 두 사용법의 차이점에 유의하십시오.

$ echo -n "$(echo -n 'a\nb')"
a
b

$ !! | xxd -p
610a62

$ echo -n  $(echo -n 'a\nb')
a b

$ !! | xxd -p   
612062

두 번째 예에서 출력은 인용되지 않았고 개행은 단어 분리로 해석되어 출력에 공백으로 표시되었습니다!


1
감사합니다 Caleb .. 인용 부호가없는 경우 공백을 단일 공백으로 바꾸는 단어 분리를 알고있었습니다. 의 '정상적인'행동 때문이다 명령 대체 링크를 위해, 아 글쎄 ... 후행 줄 바꿈을 삭제 셀라 VIE .. 감사
Peter.O

6

명령 대체를 사용할 때 쉘은 서브 쉘에서 명령을 실행하여 stdout을 리턴합니다. 이 과정에서 IFS 문자는 따옴표가 일반 분할 단어를 반환하므로 후행 단어가 제거되므로 IFS 문자의 의미가 따옴표로 표시되지 않습니다. 예를 들면 다음과 같습니다.

$ echo "$(echo -e '\n')" | wc
 1       0       1

$ echo -e '\n' | wc
2       0       2

더 실질적으로, pwd디렉토리 이름 사이에 줄 바꿈이 있어도 작동하지만 $(pwd)그렇지 않습니다.

일반적인 해결 방법은 명령 끝에 무언가를 추가 한 후 제거하는 것입니다.


1
당신의 예는 이해하기 위해서는 감사 Philomath이 ... 그런데, 당신이 첫 번째 예는 문법적으로 잘못된 것입니다 .. ( '화장실'은 인수로 문자열을 허용하지 않습니다), 첫 번째가 될 수있다 echo "$(echo -e '\n')" | wc, 이는 출력 1   0   1에 비해,2   0   2
Peter.O

@ 프레드 : 죄송합니다. 오타입니다.
Philomath

1
"공백으로 변환"은 적절한 설명이 아니며, 일부 분리 만 포함됩니다. 특히 IFS에서 공간을 제거 할 수 있으며 구분 기호로 작동하지 않습니다. 더 이상 당신의 예는 특별한 경우의 범주에 폭포 사이의 차이가 $(pwd)"$(pwd)"갈렙의 답변을 참조하십시오.
Stéphane Gimenez

추신 .. 일반적인 해결 방법에 대한 제안은이 문제를 해결하는 데 필요한 것입니다.
Peter.O

"공백으로 변환", 단어 분할
베드로
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.