두 가지 쉘 샘플을 고려하십시오.
$ ls
myDoc.html
SomeDirectory
someDoc.txt
그리고
$ echo $(ls)
myDoc.html SomeDirectory someDoc.txt
내가 이해한 바로는 수행되는 첫 번째 작업은 ls
현재 작업 디렉터리의 내용을 파일에 추가하는 것입니다 stdout
(이것이 터미널에 표시되는 내용입니다). 맞습니까?
두 번째는 명령의 값 ls
(현재 작업 디렉터리의 내용을 의미)을 가져와서 파일에 인쇄합니다 stdout
. 맞습니까?
이 두 명령이 서로 다른 출력을 제공하는 이유는 무엇입니까?
답변1
이 명령을 실행하면:
ls
터미널에 표시되는 출력입니다 ls
.
이 명령을 실행하면:
echo $(ls)
쉘은 출력을 캡처 $(ls)
하고 실행합니다.분사위에. IFS
모든 공백 시퀀스를 의미하는 기본값을 사용하고 ,포함하다줄 바꿈은 단일 공백으로 대체됩니다. 이것이 바로 출력이 echo $(ls)
한 줄에 나타나는 이유입니다.
단어 분할에 대한 고급 논의는 다음을 참조하세요.그렉 FAQ.
분사를 억제하다
쉘은 인용된 문자열에 대해 토큰화를 수행하지 않습니다. 따라서 다음을 통해 단어 분리를 억제하고 여러 줄 출력을 보존할 수 있습니다.
echo "$(ls)"
ls
및 다중 라인 출력
ls
한 줄에 여러 파일이 인쇄되는 경우가 종종 있습니다 .
$ ls
file1 file2 file3 file4 file5 file6
ls
이는 출력이 터미널로 갈 때의 기본 설정입니다 . 출력이 터미널로 직접 전송되지 않으면 ls
기본값을 한 줄에 하나의 파일로 변경합니다.
$ echo "$(ls)"
file1
file2
file3
file4
file5
file6
이 동작은 에 설명되어 있습니다 man ls
.
또 다른 미묘함: 명령 대체 및 후행 개행
$(...)
예명령 대체쉘은 출력에서 후행 개행 문자를 제거합니다.명령 대체. 기본적으로 echo
출력 끝에 개행 문자를 추가하기 때문에 이는 일반적으로 눈에 띄지 않습니다. 따라서 의 끝에서 줄바꿈을 잃고 $(...)
에서 줄바꿈을 얻으면 echo
아무 것도 바뀌지 않습니다. 그러나 명령 출력이 다음으로 끝나는 경우2개 이상개행 echo
문자 하나만 다시 추가되더라도 출력에서는 하나 이상의 개행 문자가 손실됩니다. 예를 들어, 후행 줄 바꿈을 생성하는 데 사용할 수 있습니다 printf
. 다음 명령은 모두 개행 개수가 다르지만 하나의 빈 줄에 대해 동일한 출력을 생성합니다.
$ echo "$(printf "\n")"
$ echo "$(printf "\n\n\n\n\n")"
$
이 동작은 에 설명되어 있습니다 man bash
.
또 다른 놀라움: 경로 이름 확장, 두 번
세 개의 파일을 만들어 보겠습니다.
$ touch 'file?' file1 file2
ls file?
다음의 차이점을 관찰하세요 echo $(ls file?)
.
$ ls file?
file? file1 file2
$ echo $(ls file?)
file? file1 file2 file1 file2
echo $(ls file?)
파일 글로브가 file?
확장된 경우두 배, 파일 이름 file1
이 file2
출력에 두 번 표시됩니다. Jeffkins가 지적했듯이, 이는 다음과 같습니다.경로명 확장실행하기 전에 먼저 ls
셸에서 실행한 다음 echo
실행하기 전에 다시 실행합니다.
두번째경로명 확장큰따옴표를 사용하면 이를 억제할 수 있습니다.
$ echo "$(ls file?)"
file?
file1
file2
답변2
ls
터미널로 출력을 보내고 있는지 확인하십시오.
명령 프롬프트에서 실행하면 ls
의사 터미널에 기록됩니다. ls
일반적으로 will의 출력을 리디렉션합니다.아니요의사 터미널을 입력하고 ls
출력 형식이 다르게 지정됩니다.