sed를 사용하여 두 문자열의 모든 발생을 깨끗하게 교환하십시오. 가정합니다. StringA의 모든 항목을 StringB로 바꾸고 (동시에)

StringA와 StringB가 여러 번 포함 된 파일이 있다고 가정합니다. StringA의 모든 항목을 StringB로 바꾸고 (동시에) StringB의 모든 항목을 StringA로 바꾸고 싶습니다.

지금, 나는 같은 일을하고있다

cat file.txt | sed 's/StringB/StringC/g' | sed 's/StringA/StringB/g' | sed 's/StringC/StringA/g'

이 접근법의 문제점은 파일에서 StringC가 발생하지 않는다고 가정한다는 것입니다. 이것이 실제로 문제가되지는 않지만이 솔루션은 여전히 ​​더럽습니다. 즉, 더 많은 유닉스 마법을 배울 수있는 기회 인 것 같습니다. 🙂



답변

경우 StringBStringA같은 입력 행에 표시 할 수 없습니다, 당신은 대체 한 방법을 수행하고, 거기에 첫번째 전혀 발생은 없었다 문자열을 검색 할 경우에만 다른 방법을 시도 나오지도 알 수 있습니다.

<file.txt sed -e 's/StringA/StringB/g' -e t -e 's/StringB/StringA/g'

일반적인 경우에는 sed에 쉬운 방법이 없다고 생각합니다. 그런데, 노트는 사양 경우 모호한 것을 StringAStringB겹칠 수 있습니다. 다음은 Perl 솔루션입니다. 문자열의 가장 왼쪽에있는 부분을 대체하고 반복합니다.

<file.txt perl -pe 'BEGIN {%r = ("StringA" => "StringB", "StringB" => "StringA")}
                    s/(StringA|StringB)/$r{$1}/ge'

POSIX 도구를 고수하려면 awk가 좋습니다. Awk는 일반적인 매개 변수화 된 대체를위한 기본 요소를 가지고 있지 않으므로 직접 롤백해야합니다.

<file.txt awk '{
    while (match($0, /StringA|StringB/)) {
        printf "%s", substr($0, 1, RSTART-1);
        $0 = substr($0, RSTART);
        printf "%s", /^StringA/ ? "StringB" : "StringA";
        $0 = substr($0, 1+RLENGTH)
    }
    print
}'

답변

현재, 나는 다음과 같은 일을하고 있습니다

이 접근법의 문제점은 파일에서 StringC가 발생하지 않는다고 가정한다는 것입니다.

나는 당신의 접근 방식이 훌륭하다고 생각합니다. 줄 대신에 (패턴 공간에서) 발생할 수없는 문자열 대신 다른 것을 사용해야합니다. 가장 좋은 후보는 \newline입니다.
일반적으로, 패턴 영역에 입력 된 라인의 모든 발생 스왑, 그래서 문자를 포함하지 않습니다 THISTHAT파일에를, 당신은 실행할 수 있습니다 :

sed 's/THIS/\
/g
s/THAT/THIS/g
s/\n/THAT/g' infile

또는 sed가 \nRHS에서도 지원하는 경우 :

sed 's/THIS/\n/g;s/THAT/THIS/g;s/\n/THAT/g' infile

답변

“nonce”문자열을 사용하여 두 단어를 바꾸는 것이 타당하다고 생각합니다. 보다 일반적인 솔루션을 원하면 다음과 같이 할 수 있습니다.

sed 's/_/__/g; s/you/x_x/g; s/me/you/g; s/x_x/me/g; s/__/_/g' <<<"say you say me"

그 결과

say me say you

x_x“x_x”문자열이있는 경우 교체를 피하려면 여기에 두 개의 추가 대체가 필요합니다 . 그러나 그조차도 여전히 awk나를위한 솔루션 보다 간단 해 보입니다 .