알려진 두 문자열 사이의 문자 제거

알려진 두 문자열 사이의 문자 제거

다음과 같은 데이터 세트가 있습니다.

\"XXX \ START sapiodj \\" aj \d 2387 END hddo\" START bbcc  \\" END ss

\내 요구 사항: START와 END 사이에 있는 모든 백슬래시와 큰따옴표를 제거하고 싶습니다 ."

원하는 출력:

\"XXX \ START sapiodj  aj d 2387 END hddo\" START bbcc   END ss

노트:

  1. 같은 줄에 여러 개의 START/END
  2. 다른 곳에서는 삭제하지 않고 START 와 END 사이의 \및 만 삭제하고 싶습니다."
  3. 내 파일에 여러 줄이 있습니다(위에 표시된 것과 유사).
  4. sed그냥 사용해야겠어요

다음과 같은 방법을 시도했지만( "먼저 개별적으로 제거하려고 시도) 원하는 결과를 얻지 못했습니다.

sed '/START/,/END/ s/"//g'

답변1

`파일에 문자가 없다고 가정합니다. 아래의 모든 줄을 다른 문자로 변경하면 `해당 문자는 입력에 나타나지 않습니다.

sed -e 's/END/`/g;:X' -e 's/\(START[^`]*\)["\]/\1/g;tX' -e 's/`/END/g'

답변2

실제로 그것은 어렵지 않습니다 sed. \n섹션을 분리하려면 언제든지 ewline을 사용할 수 있습니다.또는\n임시로 구분 기호를 ewline으로 변경할 수 있습니다.그리고루프 없이 이 작업을 수행할 수 있습니다.

sed 's/$/START/;s/END/&
/g;  y/D\n/\nD/
     s/\([^D]*START\)*[D\"]*/\1/g
     y/\n/D/;s/.....$//
' <<\IN                                           
\"XXX \ START sapiodj \\" aj \d 2387 END hddo\" START bbcc  \\" END ss
IN

때로는 사물을 다르게 생각해야 할 때도 있습니다. 사이에 있는 모든 것을 삭제하는 대신 줄의 시작과 문자열, 줄의 마지막과 끝 사이에 발생할 때만 저장하는 방법에 대한 질문을 돌리는 것이 더 쉬울 것 입니다 \\".STARTEND\\"STARTSTARTENDEND(물론 이것이 직관적으로 사실이 아니라면). 이는 0개 이상의 일치 항목이 sed처리되는 방식 때문입니다.*g현지 s///대체문맥.

처음부터 첫 번째 START비트는 나머지 비트의 자연스러운 결과로 지워지지 만 END마지막부터 끝까지의 비트는 지워지지 않습니다. 따라서 START줄 끝에 다른 비트를 추가해야 합니다. 추가 콘텐츠를 얻은 후 각 항목에 ewline 문자를 추가 START합니다 . 그런 다음 음역 명령을 사용하여 모든 문자를 동시에 ewline으로 바꾸거나 그 반대로 바꿉니다. 그런데 여기에서는 음역 명령이 매우 편리할 뿐만 아니라 대체 명령보다 더 효율적입니다.\nENDy///D\ny///s///

이 시점에서 l패턴 공간은 다음과 같이 인쇄됩니다.

\\"XXX \\ START sapiodj \\\\" aj \\d 2387 EN\nD hddo\\" START bbcc  \\\\" EN\nD ssSTART$

보시다시피, 이제 \\"저장해야 하는 모든 문자가 줄의 시작 부분이나 Da와 문자열 사이에 있고 그 사이에 s가 없습니다 START. D따라서 원하지 않는 문자(추가 s 포함)를 제거하는 전역 대체는 g자체적으로 저장해야 하는 문자도 대체합니다. 마지막으로 와 s를 다시 바꾸고 마지막 항목을 삭제하면 됩니다.s///D\nDSTART

이렇게 하면 필드를 안정적으로 구분할 수 있습니다.sed 입력에 관계없이그리고 표시되지 않는 문자에 의존하는 것이 아니라 줄에 절대 표시되지 않는 문자( \n물론 ewline 문자)에 의존합니다.

완료되면 인쇄하십시오.

\"XXX \ START sapiodj  aj d 2387 END hddo\" START bbcc   END ss

답변3

그리고 sed:

sed 's/:/::/g;s/</:l/g;s/>/:g/g; # escape :, <, >
     s/START/&</g; s/END/>&/g;   # replace START/END with <>
     :1
     s/\(<[^>]*\)[\"]/\1/g;t1
     s/[<>]//g;s/:g/>/g;s/:l/</g;s/::/:/g; # restore <>:'

그리고 perl:

perl -pe's|START.*?END|$&=~y/\\"//rd|ge'

답변4

당신은댓글로 지적해이것도 awk허용됩니다. 그래서 내 대답은 그것에 근거합니다.

STARTs와 s가 균형을 이룬다고 가정하고 END두 단어 중 한 줄을 분할하면 모든 짝수 필드에서 백슬래시와 큰따옴표를 제거하려는 경우가 발생합니다. 이를 위해:

awk -F 'START|END' '{
                      for(i=2;i<=NF;i+=2){ # For each even-numbered field
                        gsub(/["\\]/,"",$i) # Remove " and \ from it
                        $i="START"$i"END" # Put START and END back around it
                      }
                    }' your_file

이는 귀하의 구현에 제가 보장할 수 없는 기능이 awk있다고 가정합니다.gsub

참고로 기본적으로 " 줄 일치로 시작하고 끝나는 줄 범위 sed에 대체 적용 "이라고 표시되어 있으므로 작동하지 않습니다.STARTEND

관련 정보