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가 발생하지 않는다고 가정한다는 것입니다. 이것이 실제로 문제가되지는 않지만이 솔루션은 여전히 더럽습니다. 즉, 더 많은 유닉스 마법을 배울 수있는 기회 인 것 같습니다. 🙂
답변
경우 StringB
와 StringA
같은 입력 행에 표시 할 수 없습니다, 당신은 대체 한 방법을 수행하고, 거기에 첫번째 전혀 발생은 없었다 문자열을 검색 할 경우에만 다른 방법을 시도 나오지도 알 수 있습니다.
<file.txt sed -e 's/StringA/StringB/g' -e t -e 's/StringB/StringA/g'
일반적인 경우에는 sed에 쉬운 방법이 없다고 생각합니다. 그런데, 노트는 사양 경우 모호한 것을 StringA
및 StringB
겹칠 수 있습니다. 다음은 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가 발생하지 않는다고 가정한다는 것입니다.
나는 당신의 접근 방식이 훌륭하다고 생각합니다. 줄 대신에 (패턴 공간에서) 발생할 수없는 문자열 대신 다른 것을 사용해야합니다. 가장 좋은 후보는 \n
ewline입니다.
일반적으로, 패턴 영역에 입력 된 라인의 모든 발생 스왑, 그래서 문자를 포함하지 않습니다 THIS
및 THAT
파일에를, 당신은 실행할 수 있습니다 :
sed 's/THIS/\
/g
s/THAT/THIS/g
s/\n/THAT/g' infile
또는 sed가 \n
RHS에서도 지원하는 경우 :
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
나를위한 솔루션 보다 간단 해 보입니다 .