gawk就地和标准输出


10

是否可以使用gawk-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替代方法吗?还是有一种更清洁的方法来将该块打印到备用流?


2
在这种特殊情况下,您可能想要运行类似的find -type f -name 'myfiles' -exec grep -q 'pattern' {} \; -print -exec gawk -i inplace '{do_your_sub_and_print_to_dev/stderr_too}' {} \;方式,您将仅使用awk编辑实际上包含与该模式匹配的行的文件。
don_crissti

@don_crissti我经常忘记快得多grep。我的第一个直觉是避免不得不对文件进行两次“处理”,但是即使它确实更快,我也不会感到惊讶。它只是说明了为什么我可以相信我对分析工作的直觉
Eric Renouf

1
是的,它非常快,请记住:1)如果没有匹配项,则只处理一次文件(-print -exec gawk不再执行的部分)和2)它将在第一个匹配项处停止,因此除非第一个匹配项位于最后一行,您仍然没有处理整个文件两次(更像是1.X倍)。另外,如果gawk -i inplacesed -i这样工作,无论如何都将在原地编辑文件-即即使没有任何编辑也要更新时间戳,inode等...
don_crissti

Answers:


13

您应该使用/dev/stderr/dev/fd/2代替/proc/self/fd/2gawk手柄/dev/fd/x/dev/stderr本身(无论系统是否有这些文件或没有)。

当您执行以下操作时:

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

gawk做了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/fd是特定于Linux的,在Linux上它们是有问题的。当stderr指向常规文件或其他可搜索文件或套接字(套接字将失败)时,上述两个版本并不等效(更不用说浪费文件描述符了)。

话虽如此,如果您需要写入原始标准输出,则需要将其保存在另一个fd中,例如:

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

gawk确实使用原位重定向标准输出到文件。这是必需的,因为例如,您需要:

awk -i inplace '{system("uname")}' file

uname输出存储到file


2

只是为了好玩,只使用POSIX的替代方法的特点findshgrep和(最显着的)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 {} +

:)


(此命令未经测试;如果犯了任何错误,欢迎进行编辑。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.