bash backtick 연산자가 줄 바꿈을 출력으로 유지하려면 어떻게해야합니까?


36

bash가 백틱 대체에서 줄 바꿈을 먹지 못하게하는 방법이 있습니까?

예를 들면 다음과 같습니다.

var=`echo line one && echo line two`
echo $var

line one line two

내가 원하는 것은

var=`echo line one && echo line two` # plus some magic
echo $var

line one
line two

답변:


54

백틱 대체와 관련된 문제는 아니지만 echo; 제어 문자를 작동 시키려면 변수를 인용해야합니다.

$ var=`echo line one && echo line two`
$ echo "$var"
line one
line two

따라서 bash는 command-lien에서 변수를 확장하면서 줄 바꿈을 제거합니까? 변수를 인용하여 해당 동작을 비활성화 할 수 있습니까?
slowpoison

7
bash인용, 명령을 실행하기 전에 수행하는 매개 변수 확장 통보 할 필요가 bash당신은 하나의 문자열이 아니라 4 단어를 인쇄 할 것을 ( line, one, linetwo). 시도 : echo a <many spaces> becho "a <many spaces> b". 이 답변 도 살펴보십시오 .
cYrus

5

@cyrus는 정확하지만 실제로 전체 질문에 대답하지는 않으며 무슨 일이 일어나고 있는지에 대한 설명이 없습니다.

따라서 살펴 보겠습니다.

문자열의 개행

먼저 예상되는 바이트 순서를 결정하십시오.

$ { echo a; echo b; } | xxd
0000000: 610a 620a                                a.b.

이제 명령 대체 (3.5.4 단원) 를 사용하여이 바이트 시퀀스를 캡처하십시오.

$ x=$( echo a; echo b; )

그런 다음 간단한 에코를 수행하여 바이트 시퀀스를 확인하십시오.

$ echo $x | xxd
0000000: 6120 620a                                a b.

따라서 첫 번째 줄 바꿈이 공백으로 바뀌고 두 번째 줄 바꿈이 그대로 남았습니다. 그런데 왜?

실제로 무슨 일이 일어나고 있는지 봅시다 :

먼저, bash는 쉘 매개 변수 확장을 수행합니다 (3.5.3 절).

'$'문자는 매개 변수 확장, 명령 대체 또는 산술 확장을 소개합니다. 확장 될 매개 변수 이름 또는 기호는 중괄호로 묶을 수 있으며, 선택 사항이지만 변수가 이름 바로 뒤에 오는 문자에서 확장되도록 변수를 보호하는 역할을합니다 (이름의 일부로 해석 될 수 있음).

그런 다음 bash는 단어 분리를 수행합니다 (3.5.7 절).

쉘은 단어 분리를 위해 큰 따옴표 안에없는 매개 변수 확장, 명령 대체 및 산술 확장의 결과를 스캔합니다.

쉘은 $ IFS의 각 문자를 분리 문자로 취급하고 다른 확장 결과를이 문자의 단어로 나눕니다. IFS가 설정되어 있지 않거나 값이 정확히이면 ...

다음으로 bash는이를 간단한 명령 으로 처리합니다 (3.2.1 단원)

간단한 명령은 가장 자주 발생하는 명령입니다. 쉘의 제어 연산자 중 하나에 의해 종료되고 공백으로 구분 된 일련의 단어 일뿐입니다 (정의 참조). 첫 번째 단어는 일반적으로 실행할 명령을 지정하고 나머지 단어는 해당 명령의 인수입니다.

공백 정의 (섹션 2-정의)

공백 공백 또는 탭 문자.

마지막으로, bash는 echo (4.2-Bash Builtin Commands) 내부 명령을 호출합니다.

... 공백으로 구분 된 args를 개행 문자로 출력합니다. ...

요약하면, 줄 ​​바꿈은 Word Splitting에 의해 제거 된 다음 echo가 "a"및 "b"2 개의 인수를 가져온 다음 공백으로 구분하여 줄 바꿈으로 끝냅니다.

@cyrus가 제안한 것을 수행하고 (-n을 사용하여 줄 바꿈에서 줄 바꿈을 억제) 결과가 더 좋습니다.

$ echo -n "$x" | xxd
0000000: 610a 62                                  a.b

문자열 끝에 줄 바꿈

그래도 완벽하지는 않지만 후행 줄 바꿈이 사라졌습니다. 명령 대체 (3.5.4 단원) 자세히 살펴보기 :

Bash는 명령을 실행하고 명령 대체를 명령의 표준 출력으로 바꾸고 확장 줄 바꿈을 삭제하여 확장을 수행합니다.

줄 바꿈이 사라지는 이유가 명확 해지면 bash를 유지해야합니다. 이렇게하려면 끝에 추가 문자열을 추가하고 변수를 사용할 때 제거하십시오.

$ x=$( echo a; echo b; echo -n extra )
$ echo -n "${x%extra}" | xxd
0000000: 610a 620a                                a.b.

TL; DR

출력 끝에 추가 부분을 추가하고 변수를 인용하십시오.

$ cat /no/file/here 2>&1 | xxd
0000000: 6361 743a 202f 6e6f 2f66 696c 652f 6865  cat: /no/file/he
0000010: 7265 3a20 4e6f 2073 7563 6820 6669 6c65  re: No such file
0000020: 206f 7220 6469 7265 6374 6f72 790a        or directory.
$ cat /no/file/here 2>&1 | cksum
3561909523 46
$ 
$ var=$( cat /no/file/here 2>&1; rc=${?}; echo extra; exit ${rc})
$ echo $?
1
$ 
$ echo -n "${var%extra}" | xxd
0000000: 6361 743a 202f 6e6f 2f66 696c 652f 6865  cat: /no/file/he
0000010: 7265 3a20 4e6f 2073 7563 6820 6669 6c65  re: No such file
0000020: 206f 7220 6469 7265 6374 6f72 790a        or directory.
$ echo -n "${var%extra}" | cksum
3561909523 46

0

나는 cYrus의 답변에 대한 논평에 약간의 추가 사항을 넣었을 것이지만, 나는 생각하는 답변에 대해서는 아직 언급 할 수 없습니다. 그래서 나는 완성도에 대한 그의 대답을 cYrus의 일부로 복제 할 것입니다.

코드의 첫 번째 줄에서 일어나는 일은 실제로 백 틱스 대체가 문서화 된 대로 대체 된 명령 출력의 마지막 줄 바꿈을 먹는다는 것 입니다. 그러나 두 줄 사이에 줄 바꿈을 먹지 않습니다.

두 번째 코드 행에서 발생하는 일은 echo가 첫 번째와 두 번째 행의 두 인수로 실행된다는 것입니다. 확장 변수를 인용하면 다음과 같이 수정됩니다. echo "$var"이렇게하면 줄 1과 줄 2 사이의 줄 바꿈이 유지됩니다. 그리고 echo모든 것이 괜찮습니다, 그래서 기본적으로 후행 줄 바꿈을 추가합니다.

이제 일부 명령 대체 출력에서 ​​모든 후행 줄 바꿈을 유지하려면 해결 방법은 명령 대체 후에 제거 할 수있는 출력을 다른 행에 추가하는 것입니다 ( 여기 참조) .

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