awk 可以跳过不存在的文件吗?

Posted

技术标签:

【中文标题】awk 可以跳过不存在的文件吗?【英文标题】:Can awk skip files which do not exist, race-free? 【发布时间】:2010-09-18 01:09:54 【问题描述】:

有没有办法让 awk (gawk) 忽略或跳过丢失的文件?也就是说,通过命令行传递的文件不再存在于文件系统中(例如 /proc/[1-9]* 下快速出现/消失的文件)。

默认情况下,丢失文件是致命错误:-(

我希望能够做类似这样的事情:

BEGIN  MISSING_FILES_ARE_FATAL = 0   # <- Wishful thinking!
       count++ 
END    print count 

包装脚本无法在 awk 运行之前检查文件是否存在,因为它们可能会在检查它们和 awk 尝试打开它们之间消失,即,这是一个竞争条件。 (在awk中check-then-open也是一种竞争条件,虽然时间比较紧)

【问题讨论】:

【参考方案1】:

GAWK 4 有BEGINFILE,您可以在其中测试ERRNO,如果ERRNO 不为空(表示文件无法打开),则执行nextfile

【讨论】:

【参考方案2】:

即使在你的 awk 脚本周围加上一个 perl 或 shell 包装器,我认为仍然会有竞争条件。例如,使用 ADEpt 的其他很好的 shell sn-p:

[ -r "$filename" ] && awk -f ... $filename

没有什么可以阻止进程在 -r 和 awk 尝试打开文件之间消失...

我能想到的唯一答案是使用 LD_PRELOAD 代替 awk 的系统打开调用,这样如果文件丢失,则打开 /dev/null 上的读取文件描述符。

这可能行得通...

【讨论】:

【参考方案3】:

你可以通过系统调用检查ARGV的内容,然后通过getline处理它们。

 if (system("test -r " ARGV[1]) == 0)
   while ( (getline aline < ARGV[1]) >0 )
     # process ARGV[1] via `aline` instead of $0

...

然后处理ARGV[2]等 高温

【讨论】:

【参考方案4】:

在我看来,“MISSING_FILES_ARE_FATAL = 0”功能将成为下一个 gawk 版本的一部分。查看当前 gawk-stable 源代码的 ChangeLog 文件:

--- 剪断 ---

2008 年 8 月 22 日星期五 14:43:49 Arnold D. Robbins

* io.c (nextfile): Users Strong In The Ways Of The Source can use
non-existant files on the command line without it being a fatal error.

--- 剪断 ---

http://cvs.savannah.gnu.org/viewvc/gawk-stable/ChangeLog?revision=1.87&root=gawk&view=markup

赫尔曼

【讨论】:

【参考方案5】:

按照最好的传统,我将使用 Perl 程序回答您的 awk 问题。

#!/usr/bin/perl -w

for my $file (@ARGV) 
    open my $fh, $file or next;
    while(<$fh>) 
        ...do your thing here...
    

(这不是 awk,但它是唯一没有竞争条件的解决方案。)

【讨论】:

【参考方案6】:

哦,对不起。忽略我之前的回答。这是另一个建议:

cat /proc/[1-9]* 2>/dev/null | awk ....

Cat 会吞噬所有文件,无论是丢失的还是现有的,cat 的错误都会被遗忘(丢失的文件对 cat 来说是非致命错误),并且 awk 将能够处理结果。

【讨论】:

以上是关于awk 可以跳过不存在的文件吗?的主要内容,如果未能解决你的问题,请参考以下文章

Mysql插入数据:不存在则插入,存在则跳过或更新

shell 判断PID是不是存在,存在则kill掉,不存在则跳过

批处理判断文件存在就运行

insert into select 时,能跳过存在的记录吗

nhibernate采取跳过不采取尽可能多的

如何使用 JsonReader 跳过不需要的值?