다음 스크립트가 저장되어 bin
있으며 정의된 변수를 기반으로 출력을 얻는 데 사용됩니다. 현재 스크립트는 열 1에 대해 실행 중이며 출력을 제공합니다. 열 1 또는 열 2와 일치할 때 출력을 제공하도록 이 스크립트를 어떻게 업데이트할 수 있습니까?
cat ~/bin/POUT
#!/bin/bash
exec awk -v arg=${1:?} '$1==arg' "${@:2}" inputfile
입력 파일 -:
DEV RETAIL RETAILDEVNode
TEST RETAILTEST RETAILTESTNode
TEST AUDIT AUDITTESTNode
QA AUDITQA AUDITQANode
PROD SALE SALEPRODNode
QA SALEQA SALETESTNode
QA FINANCE FINANCEQANode
PROD FINANCE FINANCEPRODNode
현재 예상되는 결과를 얻고 있습니다 -
$ POUT QA
QA AUDITQA AUDITQANode
QA SALEQA SALETESTNode
QA FINANCE FINANCEQANode
또한 다음과 같은 출력을 원합니다(열 2에서도 검색).
$ POUT AUDITQA
QA AUDITQA AUDITQANode
Want output like this also (put any matching value and search in column 2 aslo) ---
$ POUT DITQ
QA AUDITQA AUDITQANode
따라서 변수에 입력이 무엇이든 열 1과 열 2를 검색하여 출력을 제공해야 합니다.
답변1
#!/bin/bash
arg="${1:?}" # Capture argument value or fail
shift
awk -v arg="${arg//\\/\\\\}" 'index($1, arg) || index($2, arg)' "$@" inputfile
쉘 변수를 사용할 때는 항상 큰따옴표를 사용하십시오. (가끔 예외가 발생하는 이유를 이해할 때까지 이는 사실입니다. 그때까지는 항상 큰따옴표를 사용하십시오.)
$arg
쉘 변수는 백슬래시 처리 취소를 위해 awk
무작위로 변수를 변수에 할당합니다 .arg
awk
나머지 명령줄 인수를 전달하는 이유를 이해할 수 없습니다.awk
그리고inputfile
지속적인 소스로 제공됩니다. 그래도 의도한 경우를 대비해 보관했습니다.
답변2
가능한:
#! /bin/sh -
export ARG="${1?}"
shift
exec awk '
BEGIN{
field = 1
arg = ENVIRON["ARG"] ""
}
$field == arg' "$@" inputfile
그런 다음 이를 호출하여 CLI 이전 버전과의 호환성을 유지하면서 두 번째 필드를 POUT AUDITQA field=2
살펴볼 수 있습니다.AUDITQA
몇 가지 참고사항:
- bash 또는 sh에서 따옴표를 확장하는 것을 잊어버린 경우,
-v arg=${1?}
이는 Split+glob의 영향을 받습니다. 이는 임의의 명령 실행 취약점을 야기하므로 매우 나쁩니다. 이것은 실제로 주어진 예 중 하나입니다.bash/POSIX 쉘에서 변수를 인용하는 것을 잊어버리는 보안 위험 -v
임의의 텍스트를 전달하기 위해 맹글 백슬래시를 사용할 수 없습니다-v
. 따라서ENVIRON
위의 방법을 사용해도 아무런 문제가 없습니다 .awk
인수는 변수 할당으로 처리 되므로foo=bar.txt
파일 이름에 문자가 포함되어 있으면 . 대신=
로 전달해야 합니다 ../foo=bar.txt
foo=bar.txt
$field
및ENVION["var"]
/또는-v
숫자로 보이는 전달된 변수는 숫자 문자열로 처리되어==
결국 문자열 비교 대신 숫자 비교를 수행하게 될 수 있습니다. 항상 문자열로 처리되도록 연결하므로""
예 를 들어 인수를 사용하여 호출하면 10.0, 010 또는 1e1과 일치하지 않습니다.ENVIRON["ARG"]
10