역할 변경

역할 변경

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과 유사한 명령을 사용하는 것이 가장 좋습니다.ytr

sed -e "/^KEYWORD_1/  y/\"/'/" \
    -e "/^KEYWORD_2/  y/'/\"/" \
    file

여기의 각 명령은 sed라인 선택기로 시작하여 사이의 패턴과 일치하는 라인만 작동됨을 /^KEYWORD/나타냅니다 . 여기의 패턴은 문자로 시작하여 해당 줄의 시작 부분에 있음을 나타냅니다.sed/^

줄 선택기 뒤에는 문자를 에서 동일한 위치에 있는 문자 로 바꾸는 sed대체 명령이 옵니다 .y/set1/set2/gset1set2

문자 교환

"이제 각각 을 같은 줄에 ', 그리고 동시에 각각을 바꾸려면 다음 명령 하나만 사용할 수 있습니다 '."

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/gfoo: 줄의 모든 항목을 로 바꿉니다 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은 1awk에게 이 줄을 인쇄하라고 지시합니다.

파일로 출력하려면 쉘 >연산자를 사용하여 텍스트를 임시 파일로 리디렉션하고 명령을 통해 이전 파일을 새 파일로 바꾸십시오 mv.

관련 정보