Bash 스크립트에 몇 가지 awk 명령을 포함하려고 하는데 예상치 못한 동작이 발생했습니다. 내가 무엇을 놓치고 있는지 단서를 주실 수 있나요?
예를 들어 다음과 같은 파일이 있다고 가정합니다 list
.
1
2
3
4
이 간단한 awk
명령은 원하는 작업을 수행합니다.
$ awk -F, '{ print $1 }' list
1
2
3
4
하지만 이 명령을 bash 스크립트에 넣으면:
#!/bin/bash
echo "list:"
cat $1
echo "list after awk:"
echo `awk -F, '{ print $1 }' $1`
exit 0
나는 다음과 같은 결과를 얻습니다.
$ ./script list
list:
1
2
3
4
list after awk:
1 2 3 4
awk
캐리지 리턴 문자가 bash 스크립트에서 신비롭게 제거되었습니다.
나는 OS X의 bash와 BSD의 zsh에서 이러한 동작을 본 적이 있습니다.
어떤 아이디어가 있나요?
답변1
아니요 awk
, 쉘이 확장하는 방식입니다.
예를 들어 보겠습니다.
$ a="1
> 2
> 3
> 4"
그래서 우리는 4줄이 넘는 변수를 만듭니다. 하지만...
$ echo $a
1 2 3 4
그렇다면 왜 한 줄에만 있습니까?
$ echo "$a"
1
2
3
4
아, 안돼!
그래서 뭔가가 있어마법에 대한 echo $a
.
공백에서도 비슷한 마법을 볼 수 있습니다.
$ a="1 2 3 4"
$ echo $a
1 2 3 4
$ echo "$a"
1 2 3 4
echo
자, 이곳은 실제로 마법이 일어나는 곳이 아닙니다 . 이것이 껍질입니다. 래퍼가 없으면 "..."
쉘은 변수 확장을 시도합니다. 따라서 글로브는 다음과 같이 확장됩니다.
$ ls
a file
$ a="*"
$ echo $a
a file
$ echo "$a"
*
같은 방식으로 쉘은 반환 값이 포함된 출력을 가져와서 확장하고 이를 인수로 반환합니다.
어쨌든... 이 확장이 발생하지 않도록 하려면 "..."
.
하지만 짧은 예에서는 그렇지 않습니다.필요 echo
별말씀을요. 그냥 전화하세요 awk
.
답변2
다음 두 명령 간의 출력 차이를 살펴보세요.
$ echo `awk -F, '{ print $1 }' $1`
1 2 3 4
$ echo "`awk -F, '{ print $1 }' $1`"
1
2
3
4
첫 번째 명령에서는 명령 대체가 인용되지 않았으므로 awk의 출력은 다음의 영향을 받습니다.분사그리고경로명 확장. 분사줄 바꿈을 제거하고 공백으로 바꾸십시오. 두 번째에는 awk
큰따옴표로 묶여 있으므로 해당 내용이 없습니다.분사개행 문자를 실행하고 보존합니다.
문서
에서 man bash
:
분사
쉘은 단어 분할을 위해 큰따옴표 안에 표시되지 않는 인수 확장, 명령 대체 및 산술 확장의 결과를 스캔합니다.
쉘은 IFS의 각 문자를 구분 기호로 처리하고 이러한 문자를 필드 종결자로 사용하여 다른 확장 결과를 단어로 분할합니다. IFS가 설정되지 않았거나 해당 값이 기본값인 경우
<space><tab><newline>
이전 확장 결과의 시작과 끝 부분에 있는 ,<space>
및 의 시퀀스는 무시되고<tab>
시작이나 끝이 아닌 IFS 문자 시퀀스는 구분하는 데 사용됩니다.<newline>
단어. IFS에 기본값이 아닌 값이 있는 경우 공백 문자가 IFS 값(IFS 공백)에 있는 한 단어의 시작과 끝 부분에 있는 공백과 탭 시퀀스는 무시됩니다. IFS 공백이 아닌 IFS의 모든 문자와 인접한 IFS 공백 문자가 함께 필드를 구분합니다. 공백 문자의 IFS 시퀀스도 구분 기호로 간주됩니다. IFS 값이 비어 있으면 단어 분할이 발생하지 않습니다.명시적인 빈 매개변수("" 또는 "")는 유지됩니다. 값이 없는 매개변수 확장으로 인해 암시적으로 인용되지 않은 null 매개변수는 제거됩니다. 값이 없는 매개변수를 큰따옴표로 확장하면 빈 매개변수가 생성되고 유지됩니다.
확장이 발생하지 않으면 분할이 수행되지 않습니다.
답변3
그것은 awk가 아니라 echo
벗겨진 것입니다. 떠나려면 echo
다음을 수행하세요 awk
.
awk -F, '{ print $1 }' $1