readvar.sh라는 스크립트가 있습니다.
#! /bin/bash
a="$1"
echo "$a"
매개변수를 얻고 싶습니다.문자 그대로사용자가 입력하면,
예를 들어, 사용자가 다음을 실행하는 경우:./readvar.sh \\
\\
매개변수 주위에 따옴표 없이 출력되어야 합니다 .
그게 가능합니까?
답변1
일반적으로 말하면 이렇게 할 수 없습니다.
run 인 경우 ./readvar.sh \\
명령이 작성된 쉘은 명령줄을 구문 분석하여 공백을 단어 구분 기호로 인식하고 백슬래시를 다음 문자(다른 백슬래시)를 인용하는 것으로 인식합니다. 그런 다음 ./readvar.sh
두 단어로 끝나고 \
프로그램을 시작하여 ./readvar.sh
해당 두 단어를 프로세스를 시작하는 매개변수 목록에 넣습니다. (명령어 이름은 argv[0]
C 프로그램에 나오는 매개변수 #0 입니다.)
./readvar.sh '\'
사용자가 Perl 프로그램과 같은 것을 사용하여 스크립트를 입력하거나 시작하면 유사한 bs='\'; ./readvar "$var"
결과를 얻을 수 있습니다 . system("./readvar.sh", "\\");
스크립트에는 일반적으로 무슨 일이 일어나고 있는지 알 수 있는 방법이 없습니다.
당신이 할 수 있는 일은 쉘 입력에 적합한 형식으로 모든 인수를 인쇄하는 것입니다. 예를 들어 Bash에서는 다음을 사용합니다.
if [ "$#" -ne 0 ]; then
printf "%q " "$@"
fi
echo
출력은 Bash에서 작동하지만 $'\n'
개행 등의 형태로 따옴표를 사용하기 때문에 표준 셸에서는 작동하지 않을 수 있습니다. 또한 스크립트를 \\
사용하거나 시작할 때마다 출력됩니다 .\\
'\'
"\\"
Bash에서도 이를 남용할 수 있습니다 extdebug
. 이는 실행 중인 명령의 컨텍스트에 Bash의 DEBUG 트랩에서 볼 수 있는 명령줄을 배치합니다.
export CMDLINE
trap 'CMDLINE=$BASH_COMMAND; true' DEBUG
shopt -s extdebug
하지만 거기에 있는 명령줄은 확장되지 않으므로 를 실행하면 대신 확장된 값이 env abc=$var |grep CMD
표시됩니다 .env abc=$var
물론 추가 단계를 수행하는 Bash 셸에서 명령이 실행되지 않으면 작동하지 않습니다. 프로세스 트리의 상위에 이러한 셸이 있는 경우 CMDLINE
이전 명령을 실행하는 명령으로 설정할 수 있습니다.
이제 이러한 까다로운 해결 방법이 존재하지만 스크립트 사용자가 스크립트가 궁극적으로 수행해야 하는 작업을 달성하기 위해 다른 방법을 사용하는 것이 더 좋고 덜 놀라운 것일 수 있습니다.
답변2
read
플래그를 사용하여 호출 할 수 있습니다 -r
.
-r Backslash does not act as an
escape character. The backslash
is considered to be part of the line.
In particular, a backslash-newline pair
may not then be used as a line
continuation.
그래서:
IFS="" read -r a
echo "$a"
"\"를 입력하면 "\"가 에코됩니다. 또한 공백을 보존합니다(목표가 아닌 경우 IFS 비트를 제거할 수 있음).
매개변수로 전달하려면 작은따옴표를 사용하여 값을 변경하지 않고 그대로 두어야 합니다.
./readvar.sh '\\'
var.sh 읽기:
#!/bin/bash
IFS="" read -r a
./usevar.sh "$a"
var.sh를 사용하세요.
#!/bin/bash
echo "$1"
를 입력 \\
하면 에코 readvar.sh
됩니다 .usevar.sh
\\
텍스트의 선행 및 후행 공백을 유지하려면 IFS가 필요합니다.