구문 분석하려는 변수 주변의 인수 확장을 어떻게 방지합니까?

구문 분석하려는 변수 주변의 인수 확장을 어떻게 방지합니까?

편집하다:

더 읽기 전에 중요한 참고 사항: 이후코살로난다의 답변, 그가 내가 사용하고 있는 다른 스크립트의 버그를 지적했기 때문에 내 질문은 이제 쓸모가 없습니다. 이 버그는 이제 수정되었으며 제가 설명한 다음 오류는 더 이상 발생하지 않습니다!

$extension의 값이 확장되는 두 가지 문제가 코드에 있습니다.
두 번째 문제는 함수 자체에 있습니다.


긴 이야기 짧게

질문을 쓰기 시작했을 때 막혔지만 효과가 있는 해결책을 찾았습니다.쉘노글로브), 하지만 여전히 "글을 쓸 수 있습니까?"라는 질문이 있습니다.

이 질문에 대한 답이 나왔다고 확신하지만 bash 확장에 관한 수백 가지 주제에 빠져 있습니다.

내 경우는 다음과 같습니다.

  • 스크립트를 실행하고 싶습니다(정규식을 허용하는 옵션 패턴을 사용한다고 가정 ffmpeg).-pattern_type glob -i*.JPG
  • 논쟁하다 (말하자면 *.JPG)
  • 변수의 인수(말하자면 $extension)
  • 스크립트 매개변수의 변수(말하자면 $1)
  • 하지만 나는원하지 않는다기본적으로 쉘이 $extension유사한 패턴으로 확장되기를 원함*.JPG

이 모든 작업은 스크립트 내에서 발생합니다 script.sh.

따라서 사용자는 다음을 실행할 수 있습니다.

script.sh 'JPG' ; # where $1='JPG'

참고: 에서는 을 script.sh연결하여 *.$1많은 최종 정규식을 얻습니다.*.JPG

나는 (여기서부터) 읽는다https://stackoverflow.com/a/11456496/912046) ffmpeg인수가 수신되기 전에 쉘 확장이 발생합니다( ffmpeg쉘 확장이 발생했다는 사실조차 알지 못한 채).

${extension}나는 따옴표, 큰따옴표 또는 백슬래시를 다양한 방법으로 사용해 보았으나 성공하지 못했습니다.
다음은 몇 가지 시도입니다.

ffmpeg ... "${extension}"

원인: ( ffmpeg 1.jpg 2.jpg [...]확장 발생)

ffmpeg ... ${extension}

동일한

ffmpeg ... '${extension}'

검색 패턴으로 인해 일치하는 파일이 없습니다 ${extension}(변수 이름은 문자 그대로 사용됨).

extension="\'${extension}\'" ; # wrapping the single quotes (preventing expansion) directly in variable
ffmpeg ... ${extension}

'*.jpg'작은따옴표를 포함한 검색 패턴으로 인해 일치하는 파일이 없습니다.

ffmpeg ... \"${extension}\"

동일하지만 검색 중 "*.jpg"(큰따옴표 포함)

마침내 Shell noglob 옵션을 사용하여 성공했습니다.
다음은 흥미로운 명령입니다.

set -f ; # disable glob (prevent expansion on '*.jpg')
ffmpeg -pattern_type glob -i ${extension} movie.mp4 ;
set +f ; # restore, but what if glob was already disabled? I should not restore it then?

그런데 궁금한데, 구문 분석하려는 변수에서 스크립트 매개변수가 확장되는 것을 방지할 수 있는 다른 방법이 있나요? (그래서 변수가 더 이상 구문 분석/대체되지 않도록 확장을 방지하는 방법(작은따옴표 사용)을 알고 있습니다.)

다음과 같습니다. (하지만 문자열 연결을 읽었습니다. 보안상의 이유로 삽입을 피해야 합니다.)

ffmpeg '${extension}'
       ||           | 3
       || 2
       | 1

어디:

  • 1: 최종 결과에 대해 작은따옴표가 켜집니다.ffmpeg '*.jpg'
  • 2: extension변수가 주입되고 구문 분석됩니다..jpg
  • ffmpeg3: 수동으로 작성한 것처럼 매개변수를 수신하기 위해 작은따옴표를 닫습니다.'*.jpg'

편집: 확장 변수를 할당하는 방법에 대한 설명을 따르세요.

local extension="${2}" ;
echo $extension ;
extension="${extension:=jpg}" ; # Default on "jpg" extension
# wrapp extension type in single quotes + prefix with "*."
extension="*.${extension}" ;

그런 다음 다음과 함께 사용하십시오.

runprintcommand ffmpeg -loglevel verbose -pattern_type glob -i ${extension} "$movieName" ;

runprintcommand함수/스크립트는 다음과 같습니다 .

function runprintcommand() {
    echo "Command to run: (Note: '\\' escape character may not be printed)" ;
    echo "$*" ;
    $* ;    
}

답변1

  • 따옴표가 없는 변수는 변수 확장, 단어 분리(기본적으로 공백, 탭 및 줄 바꿈)를 거치며, 생성된 각 단어는 차례로 파일 이름 생성(와일드카드 지정)을 거칩니다.
  • 큰따옴표로 묶인 변수는 값이 확장되지만 쉘은 확장된 값을 토큰화하거나 와일드카드로 표시하지 않습니다.
  • 작은따옴표 안의 변수는 전혀 확장되지 않습니다.

예:

$ ls
script.sh
$ var='* *'
$ echo $var
script.sh script.sh
$ echo "$var"
* *
$ echo '$var'
$var

코드에는 의 값이 $extension포함된 glob 패턴으로 확장되고 glob 패턴이 내부적으로 파일 이름(그 자체의 glob 확장에 그대로 전달하려는 ffmpeg -i)과 조기에 일치하게 만드는 두 가지 문제가 있습니다.

첫 번째는 함수 호출입니다.

runprintcommand ffmpeg -loglevel verbose -pattern_type glob -i ${extension} "$movieName" ;

여기에는 ${extension}아무 것도 인용되지 않았으므로정말해당 값에서 발생하는 파일 이름 글로빙을 가져옵니다(토큰화 및).

두 번째 문제는 함수 자체입니다.

function runprintcommand() {
    echo "Command to run: (Note: '\\' escape character may not be printed)" ;
    echo "$*" ;
    $* ;    
}

여기서는 함수 호출에서 큰따옴표를 사용 $*하더라도 다시 (값을 단어로 나눈 다음) 전역을 확장하는 인용되지 않은 부분을 사용하고 있습니다 .${extension}

$*"$@"bare 대신 (큰따옴표 포함)을 사용하세요 . 이는 다음으로 확장됩니다.혼자 인용함수의 위치 매개변수입니다.

"$@"이것이 와 의 차이점입니다 "$*":

  • "$*"작은따옴표로 묶인 문자열. 이는 일반적으로 매개변수가 있는 명령을 실행하는 데 사용할 수 없습니다.
  • "$@"큰따옴표로 묶인 단어 목록. 매개변수를 사용하여 명령을 실행하는 데 사용할 수 있습니다.

답변2

쉘 글로빙을 방지하는 방법은 변수 확장을 인용하는 것입니다. (또한 일반적으로 원하는 대로 단어 분리를 중지합니다.) 물론 이것이 명령 자체가 구형 패턴을 처리하는 것을 막지는 않습니다. ffmpeg이를 위해 예를 -i들어 동일하게 적용됩니다 . find -name후자를 예로 들어 보겠습니다.

$ touch a.foo b.foo c.bar
$ extension=foo
$ set -x
$ find . -name "*.$extension"
+ find . -name '*.foo'
./b.foo
./a.foo

( +come from 으로 시작하는 줄은 set -x명령 셸을 표시합니다.실제로란. )

와일드카드 사용을 중단할 수도 있지만 set -f단어 분할에는 도움이 되지 않습니다. 변수에 공백이 포함되어 있으면 따옴표가 없는 확장이 중단됩니다 set -f.

답변3

이를 수행하기 위한 대체 구문을 찾으면 여기에 작성하겠습니다.

플래그를 사용하여 비활성화됨쉘 와일드카드(http://tldp.org/LDP/abs/html/globbingref.html), 확장을 방지합니다.

set -f ; # disable glob (prevent expansion on '*.jpg' to turn in "1.jpg 2.jpg 3.jpg...")
ffmpeg -pattern_type glob -i ${extension} movie.mp4 ;
set +f ; # restore

관련 정보