내 스크립트에 줄 입력을 가져오고 공백이나 다른 것으로 분할하지 않고 이중 공백을 제거하지 않고 단일 매개 변수처럼 "있는 그대로" 처리하고 싶습니다. 예:
# op.sh
IFS=$'\n'
echo "$*"
./op.sh one two three
one
two
three
# Desired output
./op.sh one two three
one two three
따라서 개행(입력)까지 읽혀집니다.
답변1
프로그램(스크립트, 애플리케이션 등)은 자신을 호출하는 명령줄을 볼 수 없습니다. 호출 셸에서 구문 분석되는 일련의 0개 이상의 인수를 가져옵니다.
예를 들어 실행할 때 ls f*
처리되는 것은 셸이 아닙니다. f로 시작하는 세 개의 파일이 있는 경우 쉘은 이를 다음과 같이 구문 분석하고 이를 실행할 수 있습니다. 이 경우 대신 다음 세 가지 인수를 참조하세요.ls
f*
ls f*
ls final food fred
ls
f*
./op.sh one two three
마찬가지로 셸을 실행하면 ./op.sh
공백으로 구분된 세 개의 인수 one
, two
및 로 구문 분석됩니다 three
. 공백은 구문 분석의 일부로 삭제됩니다. 다음과 같은 스크립트로 이를 볼 수 있습니다.
#!/bin/bash
for a in $*; do echo "Found * argument ($a)"; done
echo
for a in "$@"; do echo "Found @ argument ($a)"; done
echo
echo "All together, they are ($*)"
호출되면 args
실행 가능하게 만들고( chmod a+x args
) 다음과 같이 호출 할 수 있습니다.
./args one two three
해당 출력은 다음과 같습니다.
Found * argument (one)
Found * argument (two)
Found * argument (three)
Found @ argument (one)
Found @ argument (two)
Found @ argument (three)
All together, they are (one two three)
이를 실험해 보면 $*
명령줄 인수의 경우 각 인수가 공백으로 구분되고 내부 공백이 다시 구분된다는 것을 알 수 있습니다.이것은 일반적으로 작동하지 않습니다. 대신에 큰따옴표를 사용하면 "$@"
실수로 매개변수를 구문 분석하는 것을 방지할 수 있습니다. 그러나 어느 쪽이든 인수는 원래 명령줄의 복사본이 아닌 구문 분석된 인수에서 재구성됩니다.
공백을 그대로 유지하려면 문자열을 인용해야 합니다. 큰따옴표를 사용하면 $(...)
변수와 구조를 확장할 수 있습니다. 작은따옴표는 리터럴을 남깁니다. 여기서는 작은따옴표를 사용합니다.
공백 인용
./args 'one two three'
Found * argument (one)
Found * argument (two)
Found * argument (three)
Found @ argument (one two three)
All together, they are (one two three)
아포스트로피
'one more $HOME to go'
Found * argument (one)
Found * argument (more)
Found * argument ($HOME)
Found * argument (to)
Found * argument (go)
Found @ argument (one more $HOME to go)
All together, they are (one more $HOME to go)
큰따옴표
./args "one more $HOME to go"
Found * argument (one)
Found * argument (more)
Found * argument (/home/roaima)
Found * argument (to)
Found * argument (go)
Found @ argument (one more /home/roaima to go)
All together, they are (one more /home/roaima to go)
답변2
이러한 유형의 분할은 IFS와 관련이 없습니다.
한 줄을 단어로 변환하는 가장 기본적인 분할입니다.
단어는 쉘이 작업을 수행할 수 있는 단일 토큰입니다. 문장을 읽는 것과 마찬가지로 먼저 단어로 나누고 단어의 의미를 이해하세요.
이러한 분열을 피하는 유일한 방법은 인용하는 것입니다. 이것이 인용문이 발명된 근본적인 이유이다.
$ op.sh () { printf '%s\n' "$@"; }
$ op.sh one two three
one
two
three
$ op.sh "one two three"
one two three
더 이상 마법이 없습니다.