Bash 인수에서 따옴표를 유지하는 방법
전달된 인수에 따옴표를 보관하는 Bash 스크립트가 있습니다.
예:
./test.sh this is "some test"
그런 다음 이러한 인수를 사용하여 전체 인수 목록 주변의 인용문이나 인용문을 포함하여 재사용하고 싶습니다.
는 는는그용사 i를 사용해 보았다.\"$@\"됩니다.
어떻게 하면 좋을까요?
를 사용합니다."$@"는 인수를 목록으로 대체하고 공백(셸 스크립트가 호출되었을 때 한 번 분할됨)으로 다시 변환하지 않습니다.이는 인수를 다른 프로그램에 재전송하는 경우 일반적으로 필요한 인수와 동일합니다.
이것은 특수한 형식이며 정확히 이렇게 표시되는 경우에만 인식된다는 점에 유의하십시오.따옴표 안에 다른 항목을 추가하면 결과가 단일 인수로 결합됩니다.
무엇을 하려고 하고 어떤 방법으로 그것이 작동하지 않는가?
여기에는 다음 두 가지 안전한 방법이 있습니다.
1. 셸 파라미터 확장:${variable@Q}:
를 ${variable@Q}:
확장 문자열은 입력으로 재사용할 수 있는 형식으로 따옴표로 묶인 매개 변수 값입니다.
예:
$ expand-q() { for i; do echo ${i@Q}; done; } # Same as for `i in "$@"`...
$ expand-q word "two words" 'new
> line' "single'quote" 'double"quote'
word
'two words'
$'new\nline'
'single'\''quote'
'double"quote'
2. printf %q "$quote-me"
printf는 내부적으로 견적을 지원합니다.설명서에 다음과 같이 기재되어 있습니다.
%q셸 inputprintf .
예:
$ cat test.sh
#!/bin/bash
printf "%q\n" "$@"
$
$ ./test.sh this is "some test" 'new
>line' "single'quote" 'double"quote'
this
is
some\ test
$'new\nline'
single\'quote
double\"quote
$
인용된 텍스트를 사람에게 표시하는 경우 두 번째 방법이 조금 더 깨끗하다는 점에 유의하십시오.
관련:bash의 경우 POSIX sh 및 zsh: 백슬래시가 아닌 작은 따옴표로 따옴표 문자열을 지정합니다.
Yuku의 답변은 당신이 대본의 유일한 사용자일 때만 효과가 있는 반면, Dennis Williamson의 답변은 당신이 주로 문자열을 인쇄하는 것에 관심이 있고 따옴표가 없는 것을 기대한다면 훌륭하다.
인수를 의 큰따옴표로 묶은 인수로 할 때 할 수 있는 줍니다.-c「」bash ★★★★★★★★★★★★★★★★★」su:
#!/bin/bash
C=''
for i in "$@"; do
i="${i//\\/\\\\}"
C="$C \"${i//\"/\\\"}\""
done
bash -c "$C"
따라서 모든 인수는 그 주위에 인용구를 붙입니다(이 목적을 위해 이전에도 없었더라도 상관없지만). 그러나 우리는 또한 모든 탈출구를 탈출한 다음 이미 논쟁에 있었던 인용구를 탈출합니다(구문).${var//from/to}의
물론 이미 여백이 있는 것만 인용할 수 있지만, 여기서는 문제가 되지 않습니다.이와 같은 스크립트의 유틸리티 중 하나는 미리 정의된 환경변수 세트를 갖는 것입니다(또는 su를 사용하여 모든 것을 이중 따옴표로 묶지 않고 특정 사용자로 실행할 수 있습니다).
업데이트: 최근 최소한의 포킹으로 POSIX 방식으로 이 작업을 수행해야 하는 이유가 있었습니다(마지막 인쇄에서는 스크립트를 호출하는 데 사용되는 명령줄을 출력합니다.이 명령줄을 복사 붙여넣기하여 동등한 인수를 사용하여 호출할 수 있어야 합니다).
#!/bin/sh
C=''
for i in "$@"; do
case "$i" in
*\'*)
i=`printf "%s" "$i" | sed "s/'/'\"'\"'/g"`
;;
*) : ;;
esac
C="$C '$i'"
done
printf "$0%s\n" "$C"
는 로로로 바꿨다.'' 같은 할 수 때문에.$ ★★★★★★★★★★★★★★★★★」!!""--. - - -
공백이 포함된 인수는 따옴표로 묶어야 하며 따옴표로 묶어야 한다고 가정하는 것이 안전할 경우 다음과 같이 추가할 수 있습니다.
#!/bin/bash
whitespace="[[:space:]]"
for i in "$@"
do
if [[ $i =~ $whitespace ]]
then
i=\"$i\"
fi
echo "$i"
done
다음은 샘플 실행입니다.
$ ./argtest abc def "ghi jkl" $'mno\tpqr' $'stu\nvwx'
abc
def
"ghi jkl"
"mno pqr"
"stu
vwx"
이스케이프를 사용하는 대신 - VCtrlJ및 --을(VTab를) 사용하여 - 및 -을(를) 사용하여 리터럴 탭과 새 줄을 삽입할 수도 있습니다.$'...'.
Bash 문자 삽입 주의사항: Vi 키 바인딩을 사용하는 경우(set -o vi in ( - Bash (Emacs) 입니다.set -o emacs), 문자를 삽입하려면 삽입 모드가 필요합니다.Emacs 모드에서는 항상 삽입 모드입니다.
모든 주장을 다른 통역사에게 전달하기 위해 이것이 필요했습니다.결국 내게 맞는 것은 다음과 같다.
bash -c "$(printf ' %q' "$@")"
예(forward로 명명된 경우).sh) :
$ ./forward.sh echo "3 4"
3 4
$ ./forward.sh bash -c "bash -c 'echo 3'"
3
(물론 제가 사용하는 스크립트는 제 경우 노업이나 리다이렉트 등이 더 복잡하지만, 이것이 핵심입니다.)
톰 헤일이 말했듯이, 이걸 하는 한 가지 방법은printf를 사용합니다.%q적을을내내
예를 들어 다음과 같습니다.
send_all_sys.쉿
#!/bin/bash
if [ "$#" -lt 1 ]; then
quoted_args=""
else
quoted_args="$(printf " %q" "${@}")"
fi
bash -c "$( dirname "${BASH_SOURCE[0]}" )/receiver.sh${quoted_args}"
send_syslogs를 클릭합니다.쉿
#!/bin/bash
if [ "$#" -lt 2 ]; then
quoted_last_args=""
else
quoted_last_args="$(printf " %q" "${@:2}")"
fi
bash -c "$( dirname "${BASH_SOURCE[0]}" )/receiver.sh${quoted_last_args}"
리시버쉿
#!/bin/bash
for arg in "$@"; do
echo "$arg"
done
사용 예:
$ ./send_all_args.sh
$ ./send_all_args.sh a b
a
b
$ ./send_all_args.sh "a' b" 'c "e '
a' b
c "e
$ ./send_fewer_args.sh
$ ./send_fewer_args.sh a
$ ./send_fewer_args.sh a b
b
$ ./send_fewer_args.sh "a' b" 'c "e '
c "e
$ ./send_fewer_args.sh "a' b" 'c "e ' 'f " g'
c "e
f " g
사용방법:
"${@}"
예를 들어 다음과 같습니다.
# cat t2.sh
for I in "${@}"
do
echo "Param: $I"
done
# cat t1.sh
./t2.sh "${@}"
# ./t1.sh "This is a test" "This is another line" a b "and also c"
Param: This is a test
Param: This is another line
Param: a
Param: b
Param: and also c
unhammer의 예를 어레이를 사용하도록 변경.
printargs() { printf "'%s' " "$@"; echo; }; # http://superuser.com/a/361133/126847
C=()
for i in "$@"; do
C+=("$i") # Need quotes here to append as a single array element.
done
printargs "${C[@]}" # Pass array to a program as a list of arguments.
제 문제도 비슷했고, 저는 여기에 올라온 여러 가지 생각을 사용했어요.
우리는 이메일을 보내는 PHP 스크립트를 가진 서버를 가지고 있습니다.다음으로 SSH를 통해 첫 번째 서버에 접속하여 실행하는 두 번째 서버가 있습니다.
스크립트 이름은 두 서버에서 동일하며 둘 다 실제로 bash 스크립트를 통해 실행됩니다.
서버 1(로컬)의 bash 스크립트에는 다음과 같은 기능이 있습니다.
/usr/bin/php /usr/local/myscript/myscript.php "$@"
이것은 다음 위치에 있습니다./usr/local/bin/myscript리모트 서버에 의해 호출됩니다.공백이 있는 인수에서도 정상적으로 동작합니다.
그러나 리모트 서버에서는 첫 번째 서버가 견적을 수신하지 않기 때문에 동일한 논리를 사용할 수 없습니다."$@"저는 John Mudd와 Dennis Williamson의 아이디어를 인용문과 함께 옵션과 파라미터를 재현하기 위해 사용했습니다.항목에 공백이 있을 때만 이스케이프된 인용문을 추가한다는 생각이 마음에 듭니다.
리모트 스크립트는 다음과 같이 실행됩니다.
CSMOPTS=()
whitespace="[[:space:]]"
for i in "$@"
do
if [[ $i =~ $whitespace ]]
then
CSMOPTS+=(\"$i\")
else
CSMOPTS+=($i)
fi
done
/usr/bin/ssh "$USER@$SERVER" "/usr/local/bin/myscript ${CSMOPTS[@]}"
사용하는 것에 주의:"${CSMOPTS[@]}"옵션 배열을 원격 서버에 전달합니다.
여기에 올려주신 여러분 감사합니다!정말 도움이 되었어요! :)
따옴표는 bash에 의해 해석되며 명령줄 인수 또는 변수 값에 저장되지 않습니다.
따옴표로 묶은 인수를 사용하려면 사용할 때마다 따옴표를 사용해야 합니다.
val="$3"
echo "Hello World" > "$val"
게리 S로.그의 소스 코드 힌트에 나타난 위버는 파라미터 '-c'를 사용하여 bash를 호출한 후 다음 인수를 인용하는 것입니다.
예.
bash -c "<your program> <parameters>"
또는
docker exec -it <my docker> bash -c "$SCRIPT $quoted_args"
다른 프로그래밍 언어에서 모든 인수를 bash로 전달해야 하는 경우(예를 들어 실행하려는 경우)bash -c또는emit_bash_code | bash을
- 에서 사용하는 모든 작은따옴표 문자를 이스케이프합니다.
'\''. - 그런 다음 결과를 단수 따옴표로 둘러쌉니다.
의 abc'def따라서 로 변환될 것이다.'abc'\''def'... ★★★★★★★★★★★★★★★★」'\'' 해석됩니다은 첫 인용문으로 첫 번째 인용문은 인용문으로 끝납니다.기존의 견적은 첫 번째 인용문으로 종료되고, 그 다음 이스케이프된 단일 인용문으로 끝납니다.\'그러면 새로운 견적이 시작됩니다.
네, 견적을 보존하는 것은 불가능할 것 같습니다만, 제가 취급하고 있던 문제는 그럴 필요가 없었습니다.
폴더를 재귀적으로 검색하여 문자열을 GREP하는 bash 기능이 있는데, "find this string"과 같은 공백이 있는 문자열을 전달하는 것이 문제입니다.이를 bash 스크립트에 전달하면 base 인수 $n이 grep로 전달되고 grep는 이러한 인수가 서로 다르다고 믿고 있습니다.이 문제를 해결하려면 bash를 인용하여 함수를 호출하면 따옴표 내의 항목이 단일 인수로 그룹화됩니다.나는 그 주장을 따옴표로 장식하고 그것을 grep 명령어로 전달하기만 하면 되었다.
다음 단계로 따옴표가 필요한 bash에서 어떤 인수를 받고 있는지 알고 있다면 따옴표로 장식할 수 있습니다.
문자열 주위에 큰따옴표로 묶은 작은따옴표를 사용합니다.
./test.sh this is '"some test"'
그래서 작은 따옴표 안에 있는 큰따옴표도 문자열로 해석되었습니다.
단, 스트링 전체를 작은 따옴표로 묶는 것이 좋습니다.
./test.sh 'this is "some test" '
셸의 기능을 이해하거나 스크립트의 인수를 해석하기 위해 다음과 같은 간단한 스크립트를 작성할 수 있습니다.
#!/bin/bash
echo $@
echo "$@"
그런 다음 다른 문자열로 스크립트를 호출할 때 무슨 일이 벌어지는지 확인하고 테스트합니다.
언급URL : https://stackoverflow.com/questions/1668649/how-to-keep-quotes-in-bash-arguments
'programing' 카테고리의 다른 글
| Swift에서 난수를 생성하는 방법은 무엇입니까? (0) | 2023.04.22 |
|---|---|
| 도메인 객체, POCO 및 엔티티의 차이점은 무엇입니까? (0) | 2023.04.22 |
| Swift에서 사전에 요소를 추가하는 방법은 무엇입니까? (0) | 2023.04.22 |
| 키가 첫 번째 열에 없는 Excel VLOOKUP (0) | 2023.04.17 |
| 목록의 누적 합계는 어떻게 찾나요? (0) | 2023.04.17 |