awk를 사용하여 수정 사항 저장


135

나는 배우고 awk있는데 파일에 수정 사항을 저장 sed하는 -i옵션을 사용하는 것과 유사하게 파일에 변경 사항을 쓰는 옵션이 있는지 알고 싶습니다 .

리디렉션을 사용하여 변경 사항을 작성할 수 있음을 이해합니다. 그러나 awk그렇게 할 수 있는 옵션 이 있습니까?


"리디렉션을 사용하여 파일을 제자리에 편집"에 대한 일반적인 답변 은 serverfault.com/a/547331/313521 을 참조하십시오 .
와일드 카드

@ 와일드 카드. 해결책은 엄청나게 부서지기 쉽습니다. 이벤트 순서에 대한 보장은 없으며 해당 솔루션을 사용하면 데이터가 잘릴 수 있습니다. 따로, 그 사이트에 50 명의 담당자가 필요하기 때문에 해당 사이트에 직접 댓글을 달 수 없습니다. 왜 SO가 유닉스 / 리눅스와 서버 관리자 등으로 조각 난지 이해할 수 없습니다. IMO, 그건 실수 였어
William Pursell

@WilliamPursell은 "이벤트 순서를 보장하지 않습니다"는 사실이 아닙니다. 솔루션의 유일한 취약성은 내용의 길이가 명령의 최대 길이보다 큰 경우입니다. 그러나 이벤트 순서는 보장됩니다.
와일드 카드

@Wildcard 주문을 보장하는 표준은 무엇입니까?
William Pursell

@WilliamPursell은 bash 문서에 의해 보장됩니다. 다른 껍질에 대해서는 모르겠습니다. (그런데, 당신이 당신의 계정을 연결하면, 당신은 100 회 담당자 연결 보너스를 가지고 의견
Wildcard

답변:


142

최신 GNU Awk ( 4.1.0 릴리스 이후 )에는 "inplace"파일 편집 옵션이 있습니다 .

[...] 새로운 기능을 사용하여 빌드 된 "inplace"확장을 사용하여 GNU " sed -i"기능 을 시뮬레이션 할 수 있습니다 . [...]

사용법 예 :

$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1 file2 file3

백업을 유지하려면

$ gawk -i inplace -v INPLACE_SUFFIX=.bak '{ gsub(/foo/, "bar") }
> { print }' file1 file2 file3

1
@sudo_O- "inplace"데모에 감사드립니다. 당신의 대답을 올렸습니다!
lind

옵션이 제거 된 것 같습니까? 4.1.3로, 나는 "-i includefile --include = includefile"이
키스 Hughitt

1
@ Keith 나는 같은 질문을했다. 방금 시도해 보았고 4.1.3에서 작동합니다. inplace실제로 iiSeymour의 답변gawk 에 따라 포함 된 라이브러리 이므로 로 포함 될 수있는 것입니다 . inplaceincludefile
cxw 2016 년

여기서 중요한 경고 : 'seen'배열은 명령에 포함 된 모든 파일에서 중복 된 줄로 채워집니다. 따라서 각 파일에 공통 헤더가 있으면 첫 번째 파일 다음에 모든 파일에서 제거됩니다. 대신 각 파일을 독립적으로 처리하려면 * .txt에서 f와 같은 작업을 수행해야합니다. gawk -i inplace '! seen [$ 0] ++' "$ f"; 완료
Nick K9

136

GNU awk 4.1.0 이상이 없다면 ...

sed의 -i옵션 과 같은 옵션이 없으므로 대신 다음을 수행하십시오.

$ awk '{print $0}' file > tmp && mv tmp file

참고 :는 -i마술이 아니며 임시 파일을 생성하여 sed처리합니다.


GNU awk 4.1.0부터 ...

GNU awk이 기능은 버전 4.1.0 (2013 년 10 월 5 일 릴리스) 에서 추가되었습니다 . -i릴리스 된 노트에 설명 된대로 옵션을 제공하는 것만 큼 간단하지 않습니다 .

xgawk의 새로운 -i 옵션은 awk 라이브러리 파일을로드하는 데 사용됩니다. 옵션이 아닌 첫 번째 인수가 스크립트로 취급된다는 점에서 -f와 다릅니다.

inplace.awk다음과 같이 번들 포함 파일 을 사용 하여 확장을 올바르게 호출해야합니다.

$ cat file
123 abc
456 def
789 hij

$ gawk -i inplace '{print $1}' file

$ cat file
123
456
789

변수 INPLACE_SUFFIX는 백업 파일의 확장자를 지정하는 데 사용할 수 있습니다.

$ gawk -i inplace -v INPLACE_SUFFIX=.bak '{print $1}' file

$ cat file
123
456
789

$ cat file.bak
123 abc
456 def
789 hij

나는이 기능이 추가되었습니다 행복하지만 전원이 언어의 간결함에서 오는와 같이 나에게, 구현은 매우 awkish하지 않습니다 -i inplace너무 오래 8 자입니다 IMO .

공식 단어에 대한 매뉴얼 링크 입니다.


당신의 '첫번째'예제가 더 좋아서는 안됩니다 : awk '{ gsub(/foo/, "bar" ) } ; { print $0 }' file > tmp.txt && mv -v tmp.txt file?
Tony Barganski

놀랍게도 2019 년 4 월 현재 gawk 4.0.2입니다. 아무도 당신에게 그런 말을하지 못하게하면 그러한 버전을 사용할 수 있습니다.
John Lunzer

Litte 짧은 awk '{print $0}' file | sponge file사용 sponge에서 moreutils.
brablc

15

@sudo_O정답 입니다.

작동하지 않습니다.

someprocess < file > file

셸은 제어를 일부 프로세스 ( redirections ) 로 넘기기 전에 리디렉션을 수행합니다 . 재 크기가 0 (에 파일을 자릅니다 리디렉션 출력 ). 따라서 일부 프로세스가 시작되어 파일에서 읽으려고 할 때까지 읽을 데이터가 없습니다.>


14

작동하는 약간의 해킹

echo "$(awk '{awk code}' file)" > file

매력처럼 작동합니다! 그러나 awk 명령을 변수에 저장하고 멋진 트릭으로 사용할 수 있습니까?
ashrasmun

13

대안은 다음을 사용하는 것입니다 sponge.

awk '{print $0}' your_file | sponge your_file

당신은 대체 어디 '{print $0}'당신의 awk 스크립트에 의해 your_file파일의 이름으로 당신은 장소에서 편집 할.

sponge 파일에 저장하기 전에 입력을 완전히 흡수합니다.


스폰지는 얼마나 표준 / 휴대용입니까?
토마스

2
sponge의 일부입니다 moreutils. 따라서 대부분의 시스템에는 기본적으로 존재하지 않습니다. 그러나 최소한 sponge그 자체는 충분히 휴대 가능하며 거의 모든 곳에서 실행할 수있는 것처럼 보입니다 .
MarSoft

1
tee기반 솔루션과 비교 하여이 솔루션의 단점은 sponge쓰기 전에 RAM으로 모든 것을 읽으므로 큰 파일에서 정지한다는 것입니다.
MarSoft


3

임시 파일을 만들지 않고 awk 전용 솔루션을 원하고 version! = (gawk 4.1.0)에서 사용할 수있는 경우 :

awk '{a[b++]=$0} END {for(c=0;c<=b;c++)print a[c]>ARGV[1]}' file

4
그러나 이것은 전체 파일을 메모리에 버퍼링합니까? 20GB 파일을 고려하십시오.
Amit Naidu

0

티 사용

 awk '{awk code}' file | tee file

tee명령 포획 장소와 후에 실행 awk명령이 때문에에 완료 |.


5
이것은 올바르지 않습니다. 두 명령은 병렬로 실행되며 데이터는 파이프를 통해 즉시 스트리밍됩니다. 버퍼보다 큰 파일 (내 컴퓨터에서 8192 바이트)이 잘 리면 데이터가 손실됩니다.
tripflag
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.