아래와 같은 food.txt 파일이 있습니다.
mangoes|foo|faa
oranges|foo|faa
chocolates|foo|baz
교체하려고 해요부자그리고술집조건이 충족되면 baz. (여기서는 regex b*z를 사용할 생각)
현재는 아래 sed 명령어를 사용하고 있지만 기존 파일을 직접 수정하지는 않습니다. 또한 정규식(b*z)도 사용할 수 없습니다.
sed '/baz/s/foo/bar/g' food.txt
기존 파일을 직접 수정하려면 "sed" 외에 다른 방법을 제안해 주세요.
추신: 시도해 보았지만 sed -i
sed가 아닌 다른 명령을 사용하고 싶습니다.
mobaxterm(OS - Windows)을 사용하고 있습니다.
답변1
sed
이 상황에서 사용하는데 아무런 문제가 없다고 생각합니다. 이것은 작업에 적합한 도구입니다.
귀하의 명령은 (주어진 데이터에 대해) 잘 작동합니다.
$ sed '/baz/s/foo/bar/g' food.txt
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
정규식을 사용하여 |b
줄의 끝(줄의 어느 곳도 아님)으로 시작하고 끝나는 모든 문자열을 일치시킵니다.z
baz
$ sed '/|b.*z$/s/foo/bar/g' food.txt
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
파일을 변경하려면(GNU 사용 sed
):
$ sed -i '/|b.*z$/s/foo/bar/g' food.txt
또는 (모든 sed
구현):
$ sed '/|b.*z$/s/foo/bar/g' food.txt >tmpfile && mv tmpfile food.txt
다음을 사용할 수도 있습니다 awk
.
$ awk 'BEGIN { OFS=FS="|" } $3 == "baz" { $2 = "bar" }; 1' file
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
^b.*z$
또는 세 번째 필드에서 일치합니다.
$ awk 'BEGIN { OFS=FS="|" } $3 ~ /^b.*z$/ { $2 = "bar" }; 1' file
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
... 또는밀러( mlr
), 여기서 입력은 필드 구분자로 사용되는 헤더 없는 CSV 파일로 읽혀집니다 |
.
$ mlr --csv -N --fs pipe put '$3 == "baz" { $2 = "bar" }' file
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
또는,
$ mlr --csv -N --fs pipe put '$3 =~ "^b.*z$" { $2 = "bar" }' file
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
awk
또는 Miller를 사용하면 격리된 필드에 대해 패턴을 더 쉽고 안전하게 일치시킬 수 있다는 이점이 있습니다. Miller의 또 다른 이점은 CSV 인용 규칙을 이해한다는 것입니다.
답변2
awk
다음과 함께 사용 gsub()
:
awk '/baz$/ {gsub("foo", "bar")};1' food.txt
/baz$/
원하는 경우 정규식 패턴을 대신 사용하여 일치시킬 수 있습니다.패턴이 일치하면
gsub()
원하는 문자열을 바꾸십시오.
내부 편집을 위해 최신 버전의 GNU awk
(>=4.1.0)에는 내부 수정 옵션이 있습니다.
awk -i inplace '/baz$/ {gsub("foo", "bar")};1' food.txt
sponge
그렇지 않으면 GNU를 사용 moreutils
하거나 임시 파일을 사용할 수 있습니다 .
awk '/baz$/ {gsub("foo", "bar")};1' food.txt >temp_food.txt && \
mv temp_food.txt food.txt
예:
$ cat file.txt
mangoes|foo|faa
oranges|foo|faa
chocolates|foo|baz
$ awk '/baz$/ {gsub("foo", "bar")};1' file.txt
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
답변3
sed -i
필요한 것을 정확히 수행하는 것을 사용하고 싶지 않은 이유를 모르겠지만 대안은 다음과 같습니다 perl
.
$ perl -pe 's/foo/bar/g if /b*z/' food.txt
mangoes|foo|faa
oranges|foo|faa
chocolates|bar|baz
이는 -pe
"스크립트를 적용한 후 입력 파일의 각 줄을 인쇄합니다.
-i
다음을 사용하여 해당 위치에서 파일을 편집 할 수 있습니다 .
perl -i -pe 's/foo/bar/g if /b*z/' food.txt
또한 정규식은 b*z
"0 이상과 일치하고 b
뒤에 a가 오는 것을 의미합니다 z
. and를 생략하여 일치하고 일치만 하기 때문에 여기서 작동합니다 b*z
. 즉, any는 0의 예 다음에 a가 되기 때문에 어떤 것과도 일치합니다. I 사용하고 싶은 것은 b.*z(ab 다음에 0개 이상의 문자가 오고 az가 옵니다)라고 생각하세요.bar
b
a
z
z
z
b
z
perl -i -pe 's/foo/bar/g if /b.*z/' food.txt
답변4
자동 텍스트 편집을 위한 실제로 가장 좋은 도구는 다음과 같습니다.ex
.
직접 전화하는 것도 가능하겠지만 ex
, 찾아보니MobaXterm에서전화해야 해요 vim -e
.
자동 편집을 수행하는 가장 좋은 방법은MobaXterm에서(다른 *nix 시스템에서도 작동함)은 다음과 같습니다.
printf '%s\n' 'g/b.*z/s/foo/bar/g' x | vim -es food.txt
POSIX와 완전히 호환되도록 하려면 다음과 같이 변경하세요.
printf '%s\n' 'g/b.*z/s/foo/bar/g' x | ex -s food.txt
그러나 이 ex
명령을 호출하면 MobaXterm에서 제대로 작동하지 않을 수 있습니다(제가 설치한 경우에는 작동하지 않았습니다). 해당 버전이 실패하면 vim -es
이 버전의 명령을 사용해 보십시오.ex