예상치 못한 동작이 발생했습니다 bash
. 이것은 내 입력/출력입니다.
nepumuk@pc:~$ type URL
URL is a function
URL ()
{
echo -e "${_//%/\\x}"
}
nepumuk@pc:~$ URL %2f
URL
nepumuk@pc:~$ URL %2f
/
nepumuk@pc:~$ URL %2F
/
nepumuk@pc:~$ type URL
URL is a function
URL ()
{
echo -e "${_//%/\\x}"
}
nepumuk@pc:~$ URL %2f
URL
nepumuk@pc:~$ URL %2f
/
nepumuk@pc:~$ URL %2f
/
nepumuk@pc:~$ URL %2f
/
nepumuk@pc:~$ URL %2f
/
nepumuk@pc:~$ URL %2f
/
Bash 함수 파일의 해당 부분은 다음과 같습니다.
url() {
: "${*//+/ }"
echo -e "${_//%/\\x}"
}
export -f url
URL() {
echo -e "${_//%/\\x}"
}
export -f URL
URL
테스트하는 동안 변경된 사항이 있는지 확인하기 위해 항목을 변경했습니다 echo -e "${@//%/\\x}"
. 새 터미널(에뮬레이터?) 창을 열고 후자를 사용하면
nepumuk@pc:~$ URL %2f
/usr/share/bash-completion/bash_completion
nepumuk@pc:~$ URL %2f
/
nepumuk@pc:~$ URL %2f
/
정확히 재현할 수 있지만(그리고 원하는 출력을 제공하므로 전자를 사용함) 설명을 주시면 감사하겠습니다.
답변1
이전에 실행한 명령의 마지막 인수로 변수 bash
를 확장합니다($_
다른 것들 사이).
url() { : "${*//+/ }" echo -e "${_//%/\\x}" }
확장이 먼저 no-op 명령 ${*//+/ }
에 임의 인수로 전달되기 때문에 의미가 있습니다.:
이는 +
위치 인수의 s를 공백으로 바꾸고 결과 문자열을 사이의 첫 번째 문자와 연결하는 것입니다( $IFS
인용할 때 일반적인 효과).$*
그런 다음 두 번째 명령은 결과 문자열을 가져와서 %
s로 바꾸고 \x
결과를 에 전달합니다 echo
.
에서는 및 옵션이 모두 활성화되지 않은 bash
경우 일부 이스케이프 시퀀스를 확장하는 데 사용할 수 있는 옵션에 대한 지원이 내장되어 있으며, 그 중 일부는 0xHH 16진수에 해당하는 값을 가진 바이트로 확장됩니다. 따라서 해당 바이트 값으로 대체되어 실제로 URI %XX 디코딩이 수행됩니다.posix
xpg_echo
echo
-e
\xHH
%HH
:
첫 번째 명령을 제거하면 $_
두 번째 명령에는 함수를 호출하기 전에 실행되는 명령에 전달된 마지막 인수가 포함됩니다.
여기서 함수를 작성한 사람은 임시 변수 사용을 피하기 위해 이 트릭을 사용한 것 같습니다 $_
. 그러나 이로 인해 코드가 불필요하게 복잡해지고 읽고 이해하기 어려워집니다.
uri_decode() {
local IFS=' ' # make sure arguments are joined with spaces rather than
# make some assumption on what $IFS may currently contain
local tmp="$*" # positional parameters joined with spaces
tmp=${tmp//+/ } # replace +s with spaces
tmp=${tmp//[%]/\\x} # replace % with \\x. Using [%] instead of % for
# increased portability.
printf '%b\n' "$tmp" # pass the result to printf for expanding of the \x
# sequences, avoiding echo whose behaviour depends on
# the environment, and would give incorrect results
# for strings like -Enee
}
+ -> 공백 변환을 수행하지 않는 변형을 원하는 경우 해당 tmp=${tmp//+/ }
부분을 제거하면 됩니다.