고정 및 표준 출력

고정 및 표준 출력

gawk's -i inplace옵션을 사용하여 내용을 인쇄할 수 있나요 stdout?

예를 들어, 파일을 업데이트하고 변경된 사항이 있으면 파일 이름과 변경된 줄을 인쇄하려면 stderr다음과 같이 할 수 있습니다 .

find -type f -name 'myfiles' -exec gawk -i inplace '{if(gsub(/pat/, "repl")) { print FILENAME > "/proc/self/fd/2" ; print > "/proc/self/fd/2"; } print;}' {} +

stdout하지만 해당 블록을 대체 스트림으로 인쇄하는 대안이나 더 깔끔한 방법이 있습니까 ?

답변1

및 자체를 처리하려면 (시스템에 이러한 파일이 있는지 여부에 관계없이) 대신 /dev/stderr또는를 사용해야 합니다 ./dev/fd/2/proc/self/fd/2gawk/dev/fd/x/dev/stderr

다음을 수행할 때:

print "x" > "/dev/fd/2"

gawkExecute 을 write(2, "x\n")수행하는 동안:

print "x" > "/proc/self/fd/2"

특별한 처리 가 없으므로 /proc/self/fd/x다음을 수행합니다.

fd = open("/proc/self/fd/2", O_WRONLY|O_CREAT|O_TRUNC);
write(fd, "x\n");

첫 번째는 /proc/self/fdLinux에만 해당되며 Linux에서는 버그가 있습니다. 위의 두 버전은 stderr이 일반 파일이거나 다른 검색 가능한 파일 또는 소켓인 경우(후자는 실패함) 동일하지 않습니다(파일 설명자를 낭비한다는 것은 말할 것도 없습니다).

하지만 원시 stdout에 작성해야 하는 경우 다음과 같이 다른 fd에 저장해야 합니다.

gawk -i /usr/share/awk/inplace.awk '{
   print "goes into the-file"
   print "to stdout" > "/dev/fd/3"}' the-file 3>&1

gawk실제로는 stdout을 파일로 리디렉션합니다. 예를 들어 다음을 원하기 때문에 필요합니다.

awk -i /usr/share/awk/inplace.awk '{system("uname")}' file

uname출력을 에 저장합니다 file.

어떤 경우 에라도,사용하지 마세요-i inplace현재 작업 디렉터리(as or)에서 확장 기능을 먼저 gawk로드 하려고 하면 누군가가 해당 디렉터리에 악성 코드를 심었을 수 있습니다. 시스템과 함께 제공되는 확장 프로그램 의 경로 는 다를 수 있습니다. 출력을 참조하세요.inplaceinplaceinplace.awkinplacegawkgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

답변2

재미삼아 또 다른 접근 방식 은 find, shgrep(가장 주목할만한) POSIX 함수만 사용합니다 ex.

find . -type f -name 'myfiles' -exec sh -c '
  for f do grep -q "pat" "$f" &&
    { printf "%s\n" "$f";
      printf "%s\n" "%s/pat/repl/g" x | ex "$f";
  }; done' find-sh {} +

(위 명령의 모든 줄 바꿈은 선택 사항이므로 한 줄로 압축할 수 있습니다.)

또는 더 명확하게 말하면 다음과 같습니다.

find . -type f -name 'myfiles' -exec sh -c '
  for f
  do
    if grep -q "pat" "$f"; then
      printf "%s\n" "$f"
      printf "%s\n" "%s/pat/repl/g" x | ex "$f"
    fi
  done' find-sh {} +

:)


(이 명령은 테스트되지 않았습니다. 실수한 경우 자유롭게 편집하십시오.)

관련 정보