AWK를 사용하여 찾고 바꿀 때 견적이 표시되도록 하려면 어떻게 해야 합니까?

AWK를 사용하여 찾고 바꿀 때 견적이 표시되도록 하려면 어떻게 해야 합니까?

현재 저는 AWK를 사용하여 문자열의 처음 세 항목 중 일부를 찾아 교체하고 있습니다. 문자열은 다음과 같은 형식으로 지정되며 파일에는 다음과 같은 문자열이 많이 있습니다.

func(tempID="39849235",count='12');

사용이 링크, AWK를 사용하여 문자열의 처음 세 인스턴스를 찾아 바꾸는 방법을 찾을 수 있었습니다. 나는 그것을 내가 필요로 하는 것으로 변경했고, 내 스크립트의 일부는 아래와 같습니다:

id=12349876
awk 'BEGIN {matches=0}
     matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID='"$id"'"); matches++ }
     { print $0 }' filName.py >filName.py.changed

위 코드의 목표는 tempID가 포함된 모든 행을 일치시키고 tempID에 할당된 숫자를 이름이 지정된 변수에 포함된 값으로 바꾸는 것입니다 $id. 찾기 및 바꾸기는 잘 작동하지만, 내가 가지고 있는 한 가지 문제는 구조를 어떻게 구성하든 출력에서 ​​따옴표 없이 $id를 인쇄한다는 것입니다. 따옴표를 이스케이프 처리하고 단일 틱을 시도했지만 관계없이 줄은 다음과 같이 변경되었습니다.

func(tempID=39849235,count='12');

교체 부분 주위의 큰따옴표를 제거하고 로 구조화하려고 시도했지만 tempID="$id"불행하게도 이는 ID 번호를 문자열로 대체할 뿐입니다 $id.

tempID 값을 찾아서 바꾸고 값을 따옴표로 묶는 방법이 있는지 알려주십시오. 저는 AWK에만 국한되지 않으므로 sed와 같은 다른 유틸리티를 사용하는 다른 방법도 잘 작동합니다.

답변1

명령에는 쉘에 의해 해석되고 제거된 따옴표가 있고 에 의해 해석되고 제거된 따옴표가 있으며 awk, 살아남을 따옴표가 필요합니다. 당신은 그들을 탈출해야합니다 :

id=12349876
awk 'BEGIN {matches=0}
 matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\"'"$id"'\""); matches++ }
 { print $0 }' filName.py >filName.py.changed              # ^^  here ^^

설명. 원래 명령은 다음과 같습니다

awk 'BEGIN {matches=0} matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID='"$id"'"); matches++ } { print $0 }'
#   ^ these quotes are seen by the shell and don't get to awk                      ^^   ^^                            ^
#     these quotes get to awk and serve their purpose there      ^      ^  ^              ^
#     this variable is expanded by the shell and gets to awk as its value            ^^^

다음은 향상된 명령입니다.

awk 'BEGIN {matches=0} matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\"'"$id"'\""); matches++ } { print $0 }'
#   ^ these quotes are seen by the shell and don't get to awk                        ^^   ^^                              ^
#     these quotes get to awk and serve their purpose there      ^      ^  ^                  ^
#     these quotes will appear in the output thanks to being escaped                ^        ^
#     this variable is expanded by the shell and gets to awk as its value              ^^^

인용 열풍을 줄이려면 -v옵션을 사용하여 변수를 awk. 그러면 쉘이 확장되도록 하기 위해 시퀀스 중간에 작은따옴표를 닫았다가 다시 열 필요가 없습니다 $id. 대신에 인용되지 않은 부분은 awk자체적 으로 id확장됩니다 . awk추가해야 하는 큰따옴표는 이전과 같이 이스케이프 처리해야 합니다.

id=12349876
awk -v id="$id" 'BEGIN {matches=0}
 matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\""id"\""); matches++ }
 { print $0 }' filName.py >filName.py.changed

답변2

원하는 것을 달성하려면 다음을 수행해야 합니다.

큰따옴표의 경우:

  • AWK: "다른 큰따옴표 안에 큰따옴표를 이스케이프합니다.
    $1 $2=> foobar
    $1" __"$2"__"=> foo __bar__
    $1" \""$2"\""=>foo "bar"

작은따옴표의 경우:

  • Shell: 내부의 '…'다른 세트를 사용하여 전체 awk 스크립트를 종료합니다. =>'…'
    'escaped 'unescaped' escaped'
    '$LINUX '$OSTYPE' $CPUTYPE'$LINUX linux-gnu $CPUTYPE

  • Shell: 탈출을 '문자 그대로 인쇄하고 싶습니다.
    'apostrophe that'\''s literal'=>apostrophe that's literal

예를 들어

echo foo bar | awk '{print "\""$1"\" '\''"$2"'\''"}'
"foo" 'bar'

관련 정보