동일한 입력에 대해 다른 bash 출력

동일한 입력에 대해 다른 bash 출력

예상치 못한 동작이 발생했습니다 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 디코딩이 수행됩니다.posixxpg_echoecho-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//+/ }부분을 제거하면 됩니다.

관련 정보