Bash 매개변수 분할을 비활성화하는 방법은 무엇입니까?

Bash 매개변수 분할을 비활성화하는 방법은 무엇입니까?

내 스크립트에 줄 입력을 가져오고 공백이나 다른 것으로 분할하지 않고 이중 공백을 제거하지 않고 단일 매개 변수처럼 "있는 그대로" 처리하고 싶습니다. 예:

# 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로 시작하는 세 개의 파일이 있는 경우 쉘은 이를 다음과 같이 구문 분석하고 이를 실행할 수 있습니다. 이 경우 대신 다음 세 가지 인수를 참조하세요.lsf*ls f*ls final food fredlsf*

./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

더 이상 마법이 없습니다.

관련 정보