Bash 스크립트 파일에서 명령을 어떻게 매개변수화합니까?

Bash 스크립트 파일에서 명령을 어떻게 매개변수화합니까?

편집 - bash $1변수를 사용하지 않습니다. 예제에서는 필드 지정자를 사용하고 있습니다. $1, $2$3입력 awk레코드 필드입니다. 불행히도 예제를 너무 빨리 살펴서 예제가 혼동되었습니다.

나는 이것이 일반적인 문제라고 생각합니다. awk프레젠테이션 도구로 사용하고 있어요 . 목적은 (또는 모든 도구) 명령 awk에 ( ) 스크립트 매개변수를 암시하는 것입니다.awk

STDIN에서 as로 제공된 필드를 사용하여 awk결과를 생성합니다. 식별자 는 $1STDIN 스트림의 필드 입니다 $2.$3awk

필수 솔루션 A(선호 개념), 예:…

#!/bin/bash  -f
#   script: blue.sh
#
    awk -e '{ print $1 " and " $2 " silly example" ;}'
#

그리고 원하는 출력:

$  echo  "red blue yellow" > ./blue.sh 
red and blue silly example
$

아마도 대안 B를 고려할 수 있습니다.

#!/bin/bash  -f
#   script: green.sh
#
    wrk="awk -e '{ print \$3 \" and \" \$2 \" variable example\" ;}'  "
#
    echo "work is:"
    echo $wrk
    echo
    $wrk

그리고 원하는 출력:

$  echo  "red blue yellow" > ./green.sh 
wrk is:
awk -e '{ print $3 " and " $2 " variable example" ;}'  

yellow and blue variable example
$

문제는 -e표현의 참조에 있습니다.

이러한 예제를 구현할 수 있는 방법이 있나요?

답변1

이건 아마도"변수에 저장된 명령을 어떻게 실행할 수 있나요?”라고 말하지만 여러 부분으로 구성되어 있으므로 귀하의 상황에 맞게 구체적으로 답변해 드리겠습니다.

  1. 명령을 변수에 저장하고 해당 변수를 사용하여 실행하십시오.
  2. 에 데이터를 전달합니다 awk.

"변수에서 명령 실행" 비트

다음은 스크립트의 대체 구현에 대한 제안 사항입니다.

#!/bin/bash

wrk=( awk -v a="$3" -v b="$2"
      'BEGIN { printf "%s and %s variable example\n", a, b }' )

awk -v a="$1" -v b="$2" 'BEGIN { printf "%s and %s silly example\n", a, b }'

printf 'wrk is: %s\n' "${wrk[*]}"
"${wrk[@]}"

이것을 실행하세요:

$ ./blue.sh "red" "blue" "yellow"
red and blue silly example
wrk is: awk -v a=yellow -v b=blue BEGIN { printf "%s and %s variable example\n", a, b }
yellow and blue variable example

내가 한 일은 awk명령을 저장하는 것이었습니다.대량으로문자열이 아닌. 이렇게 하면 배열의 각 개별 요소를 배열의 나머지 부분과 별도로 개별 요소로 유지하면서 올바르게 참조할 수 있습니다. 예를 들어, 시작 부분의 단어 awk는 배열(전체 코드)의 마지막 항목과 awk별개의 단어 입니다.

명령으로 사용되는 경우 "${wrk[@]}"배열의 각 요소는 별도의 명령줄 인수로 사용됩니다(첫 번째 요소는 명령임). 확장 참조를 사용 "${wrk[@]}"하면 각 요소가 개별적으로 참조됩니다(를 사용해 ${wrk[@]}도 효과가 없음).

이는 변수에 명령을 저장하고 실행하는 방법입니다. 즉, 배열을 사용하고 배열 요소와 배열 확장을 올바르게 참조하는지 확인하십시오.

쉘 스크립트 호출의 경우 배열에서 단일 문자열 생성을 printf사용합니다 (기본적으로 모든 요소는 공백으로 구분됨). 이는 쉘이 배열을 생성할 때 이러한 요소를 제거하기 때문에 예상되는 개별 요소에 대한 참조를 유지하지 않는다는 것을 알 수 있습니다(유사한 작업을 수행할 때 따옴표를 제거하는 것과 같습니다 )."${wrk[*]}"wrka='hello world'

보려는 각 개별 요소에 대해 wrk다음과 같은 것을 사용하십시오 printf 'element: "%s"\n' "${wrk[@]}". 이것은 출력됩니다

element: "awk"
element: "-v"
element: "a=yellow"
element: "-v"
element: "b=blue"
element: "BEGIN { printf "%s and %s variable example\n", a, b }"

이 특별한 경우에는 필요에 따라 셸 기능을 사용할 수도 있습니다.

#!/bin/bash

wrk () {
    awk -v a="$1" -v b="$2" 'BEGIN { printf "%s and %s variable example\n", a, b }'
}


awk -v a="$1" -v b="$2" 'BEGIN { printf "%s and %s silly example\n", a, b }'

wrk "$3" "$2"

함수의 $1및 는 $2스크립트가 아닌 함수의 첫 번째 및 두 번째 매개변수를 나타냅니다.

이것을 실행하세요:

$ ./blue.sh "red" "blue" "yellow"
red and blue silly example
yellow and blue variable example

-특정 awk비트

awk 명령줄 에 데이터를 전달하기 위해 -v 초기화 awk변수를 사용합니다 awk. 이는 셸 확장을 통해 코드에 변수를 주입하는 것보다 낫습니다 awk. 이렇게 하면 사용자가 단순한 데이터가 아닌 실행 가능한 코드를 주입할 수 있기 때문입니다(예: 단순히 $3a ;및 일부 코드를 포함함으로써). awk바라보다"awk의 명령줄 매개변수" 그리고이 사이트에도 비슷한 질문이 있습니다이에 대해 자세히 알아보세요.

awk환경 변수를 사용하여 데이터를 전달할 수도 있습니다 .

a=$3 b=$2 awk 'BEGIN { printf "%s and %s variable example\n", ENVIRON["a"], ENVIRON["b"] }' )

또는,

export a="$3"
export b="$2"
awk 'BEGIN { printf "%s and %s variable example\n", ENVIRON["a"], ENVIRON["b"] }' )

또한 표준 입력에는 읽을 수 있는 입력이 없기 때문에 awk단일 블록에서 코드를 실행하고 있습니다 .BEGIN

답변2

해결책을 찾았지만 결과는 원래 생각했던 것과는 상당히 달랐습니다. bash명령에서 -script 변수를 확장하는 방법을 찾을 수 없어서 이를 "구성"해야 했습니다. xargs이는 쉘이 원하는 작업을 수행하는 방식과 관련된 여러 가지 이유로 부적절하다는 것이 밝혀졌습니다 .

실행 중인 예제를 살펴본 다음 코드를 살펴보고 무슨 일이 일어나는지 설명하겠습니다. "# (2)"와 같은 태그로 토론할 영역을 표시했습니다.

:

입력하다...

$ svn status -qu ..
M            28637   /src/line.h
M            28637   /src/line.cpp
        *    28637   /testing/CheckWindows.py

처리...

반복 스크립트는 두 가지 매개변수를 사용합니다.

  1. 입력 목록에서 실행할 템플릿 또는 하나 이상의 명령
  2. awk입력 스트림 필터링을 위한 일부 명령

명령줄:

 svn status -qu .. | repeat                                        \
                       'cp -v $ff  /mnt/testhost/testarea/r02/$ff' \
                       "{  if( $1 == "M" ){ print  $3; } }"

산출...

'/src/line.h' -> '/mnt/testhost/testarea/r02/src/line.h'
'/src/line.cpp' -> '/mnt/testhost/testarea/r02/src/line.cpp'

무슨 일이에요?

  • 로컬에서 수정된 파일만 복사r02/testarea
    • 분명히 필터링은 무엇이든 될 수 있습니다
  • 의 목적은 repeat필터링된 입력 목록에서 일련의 명령을 반복하는 것입니다.

주석이 달린 코드:

    #!/bin/bash
    #   repeat.bash

    function  repeat
    {
        local -a    actions=()
        local       DELIMITER=";"
        local       filter="${2}"
        local       cmd=""

        local       wrk="${1}${DELIMITER}"        # (1)   Template
        local       str=""


        while [[ $wrk  ]]                         # (2)   Split-up individual commands
        do
            str="${wrk%%"${DELIMITER}"*}"
            actions+=( "${str}" )

            wrk="${wrk#*"${DELIMITER}"}"
        done

        echo    "actions: "                       # (3)   Debugging code

        for action in "${actions[@]}"
        do
            echo  "        => \"${action}\"."
        done
        echo  "filter  => '${filter}'."


        ex="${filter}"                            # (4)   Awk instructions to 
                                                  #       process input stream


        for ff in $(awk -e "${ex}")               # (5)   .
        do
            for action in "${actions[@]}"         # (6)   .
            do
                cmd="${action//\$\{ff\}/${ff}}"   # (7)   .
                cmd="${cmd//\$ff/${ff}}"

                ${cmd}                            # (8)   .
            done
        done

        return

    }

    repeat  "${@:1}"                              # (9)   .

노트:

  1. Arg는 $1명령 템플릿입니다.
    *
    나중에 구문 분석을 위해 끝에 구분 기호를 추가하세요.
  2. $1일반적으로 여러 명령을 사용합니다. 입력 매개변수를 별도의 세미콜론으로 구분된 명령 문자열로 분할합니다.
  3. 확인을 위해 매개변수를 인쇄합니다.
  4. 필터를 ex변수에 로드합니다.
    *
    이 예에서는 ex필터만 으로 전달됩니다 $2.
  5. 필터링된 입력 라인에 의해 생성된 각 문자열을 반복합니다.
    *
    exawk선택/생성 필터로 실행되는 명령이 됩니다 .
  6. 모든 명령 템플릿을 반복합니다 action.
  7. $ff명령 문자열 ${ff}의 확장 구문 action.
  8. 각 파일에 대해 생성된 각 명령줄을 실행합니다 $ff.
  9. 스크립트를 실행하려면 이 함수를 호출하세요.

pout의 경우 매개변수를 awk템플릿 문자열에 직접 주입할 수 없기 때문에 이는 매우 달라집니다. 그러나 해결 방법은 그다지 불편하지 않으며 신비한 확장 기능 없이도 어떻게 작동하는지 보여줍니다.

나는 이 아이디어가 유용하다고 믿는다. 이제 작동하는 스니펫이 있으므로 매우 편리하다고 생각합니다.

관련 정보