현재 저는 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'