편집 - bash
$1
변수를 사용하지 않습니다. 예제에서는 필드 지정자를 사용하고 있습니다.$1
,$2
는$3
입력awk
레코드 필드입니다. 불행히도 예제를 너무 빨리 살펴서 예제가 혼동되었습니다.
나는 이것이 일반적인 문제라고 생각합니다. awk
프레젠테이션 도구로 사용하고 있어요 . 목적은 (또는 모든 도구) 명령 awk
에 ( ) 스크립트 매개변수를 암시하는 것입니다.awk
STDIN에서 as로 제공된 필드를 사용하여 awk
결과를 생성합니다. 식별자 는 $1
STDIN 스트림의 필드 입니다 $2
.$3
awk
필수 솔루션 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
이건 아마도"변수에 저장된 명령을 어떻게 실행할 수 있나요?”라고 말하지만 여러 부분으로 구성되어 있으므로 귀하의 상황에 맞게 구체적으로 답변해 드리겠습니다.
- 명령을 변수에 저장하고 해당 변수를 사용하여 실행하십시오.
- 에 데이터를 전달합니다
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[*]}"
wrk
a='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
. 이렇게 하면 사용자가 단순한 데이터가 아닌 실행 가능한 코드를 주입할 수 있기 때문입니다(예: 단순히 $3
a ;
및 일부 코드를 포함함으로써). 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
처리...
반복 스크립트는 두 가지 매개변수를 사용합니다.
- 입력 목록에서 실행할 템플릿 또는 하나 이상의 명령
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) .
노트:
- Arg는
$1
명령 템플릿입니다.
*나중에 구문 분석을 위해 끝에 구분 기호를 추가하세요. $1
일반적으로 여러 명령을 사용합니다. 입력 매개변수를 별도의 세미콜론으로 구분된 명령 문자열로 분할합니다.- 확인을 위해 매개변수를 인쇄합니다.
- 필터를
ex
변수에 로드합니다.
* 이 예에서는ex
필터만 으로 전달됩니다$2
. - 필터링된 입력 라인에 의해 생성된 각 문자열을 반복합니다.
*ex
awk
선택/생성 필터로 실행되는 명령이 됩니다 . - 모든 명령 템플릿을 반복합니다
action
. $ff
명령 문자열${ff}
의 확장 구문action
.- 각 파일에 대해 생성된 각 명령줄을 실행합니다
$ff
. - 스크립트를 실행하려면 이 함수를 호출하세요.
pout의 경우 매개변수를 awk
템플릿 문자열에 직접 주입할 수 없기 때문에 이는 매우 달라집니다. 그러나 해결 방법은 그다지 불편하지 않으며 신비한 확장 기능 없이도 어떻게 작동하는지 보여줍니다.
나는 이 아이디어가 유용하다고 믿는다. 이제 작동하는 스니펫이 있으므로 매우 편리하다고 생각합니다.