600개 이상의 파일에서 작은따옴표를 큰따옴표로 바꾸고 큰따옴표를 작은따옴표로 바꿔야 합니다. 나는 하루의 대부분을 다양한 주제에 관해 읽는 데 보냅니다. 나는 몇 가지 기본 쉘 스크립트 명령만 알고 정규 표현식에 익숙하지 않아서 혼란스럽습니다.
아래는 제가 만든 일반 샘플 파일입니다.
some text KEYWORD_1 table name column = "string" AND column = "string"
Additional text
.
.
.
some text KEYWORD_2 text 'text in quote' etc.
키워드를 사용하여 두 줄의 따옴표를 변경하고 싶습니다. 키워드가 항상 첫 번째 줄과 마지막 줄에 있을 것이라고 보장할 수는 없습니다. 키워드를 찾고 해당 줄의 모든 인용문만 변경하려면 내 솔루션이 필요합니다.
SED의 메타데이터를 포함하여 이 포럼의 유사한 질문에서 찾은 몇 가지를 시도했습니다. 이 명령을 사용하는 방법을 알아내려고 노력 중입니다 sed -i 's/foo\(.*baz\)/bar\1/' file
. 주제에 따르면 이 명령은 "baz가 같은 줄에서 따라오는 경우에만 foo를 bar로 바꿉니다." 내 키워드는 같은 줄 뒤에 있지 않지만 처음에 있어서 제대로 작동하지 않습니다.
나도 시도해봤는데 ex -sc 'g/DEL/s/ALF/BRA/g' -cx file
아무 것도 안 됐어요. 명령줄에서는 실행할 수 없다고 가정합니다. 600개의 파일을 모두 열고 싶지는 않습니다.
물론 한 번 시도한 결과 grep KEYWORD_1 file | sed -i "s/'/\"/g" file
한 줄이 아니라 파일의 모든 인용문이 변경되었습니다.
해결책은 간단할 거라 확신합니다. 저는 그것을 볼 수 없습니다. 어떻게 해야 하나요?
요구 사항에 따라 원하는 출력은 다음과 같습니다.
some text KEYWORD_1 table name column = 'string' AND column = 'string'
Additional text
.
.
.
some text KEYWORD_2 text "text in quote" etc.
답변1
역할 변경
한 문자 집합을 다른 문자 집합으로 변경하는 것은 일반적으로 tr
이 명령의 작업이지만 특정 줄에서만 이 작업을 수행하려면 다음 sed
과 유사한 명령을 사용하는 것이 가장 좋습니다.y
tr
sed -e "/^KEYWORD_1/ y/\"/'/" \
-e "/^KEYWORD_2/ y/'/\"/" \
file
여기의 각 명령은 sed
라인 선택기로 시작하여 사이의 패턴과 일치하는 라인만 작동됨을 /^KEYWORD/
나타냅니다 . 여기의 패턴은 문자로 시작하여 해당 줄의 시작 부분에 있음을 나타냅니다.sed
/
^
줄 선택기 뒤에는 문자를 에서 동일한 위치에 있는 문자 로 바꾸는 sed
대체 명령이 옵니다 .y/set1/set2/g
set1
set2
문자 교환
"
이제 각각 을 같은 줄에 '
, 그리고 동시에 각각을 바꾸려면 다음 명령 하나만 사용할 수 있습니다 '
."
sed -e "/^KEYWORD_1\|^KEYWORD_2/ y/\"'/'\"/" file
답변2
'
여기서 복잡한 점은 모두 를 로 바꾼 "
다음 모두를 "
로 바꾸면 '
만 남게 된다는 것입니다 '
. 따라서 먼저 '
다른 것으로 바꿔야 합니다 (예를 들어 \0
입력 파일에 나타나지 않을 것이라고 안전하게 가정할 수 있는 NULL 문자( )). 그런 다음 "
다시 '
다른 것으로 바꿔야 합니다 "
. 예를 들어 Perl에서는 다음과 같습니다.
$ perl -pe "if(/KEYWORD/){s/'/\0/g; s/\"/'/g; s/\0/\"/g}" file
KEYWORD_1 table name column = 'string' AND column = 'string'
Additional text
.
.
.
KEYWORD_2 text "text in quote" etc.
설명하다
-pe
:피주어진 스크립트를 적용한 후 각 입력 줄을 인쇄합니다-e
.if(/KEYWORD/){something}
something
: 행이 일치하는 경우에만 실행됩니다KEYWORD
.s/foo/bar/g
foo
: 줄의 모든 항목을 로 바꿉니다bar
. 이는g
"글로벌"을 의미합니다. 이것이 없으면 각 줄의 첫 번째 항목만 대체됩니다.
\"
스크립트 자체가 큰따옴표 안에 있으므로 스크립트 내의 큰따옴표는 이스케이프( )해야 합니다 .
의견에서 지적했듯이 먼저 좀 더 직접적인 접근 방식을 생각했어야 했습니다.
perl -pe "tr/'\"/\"'/ if /^KEYWORD/" file
연산자 tr
음역 문자 목록. 일반적인 형식은 입니다 tr/searchlist/replacementlist/
. 따라서 일치하는 행에서만 모두 를 '
대체 합니다 ."
"
'
KEYWORD
답변3
약간 조잡하지만 GNU awk를 사용하여 작동합니다.
$ awk -v sq="'" '/KEYWORD/{if ($0~sq){ gsub(sq,"\"")} else if ($0~"\"") gsub(/\"/,sq)};1' input.txt
KEYWORD_1 table name column = 'string' AND column = 'string'
Additional text
.
.
.
KEYWORD_2 text "text in quote" etc.
sq 변수는 작은따옴표를 나타내는 데 사용됩니다. 코드 블록 자체에 변수를 포함시키는 것은 awk에서 약간 고통스럽기 때문입니다. 기본 아이디어는 패턴을 검색하고 패턴이 발견되면 무엇을 교체할지 결정하는 것입니다. Final은 1
awk에게 이 줄을 인쇄하라고 지시합니다.
파일로 출력하려면 쉘 >
연산자를 사용하여 텍스트를 임시 파일로 리디렉션하고 명령을 통해 이전 파일을 새 파일로 바꾸십시오 mv
.