【问题标题】:Unable to filter rows which contain "Is a directory" by SED/AWK无法通过 SED/AWK 过滤包含“是目录”的行
【发布时间】:2010-10-15 06:52:13
【问题描述】:

我运行代码给了我以下示例数据

md5deep find * | awk '{ print $1 }'

输出样本

    /Users/math/Documents/Articles/Number theory: Is a directory
    258fe6853b1bfb2d07f512ff6bec52b1
    /Users/math/Documents/Articles/Probability and statistics: Is a directory
    4811bfb2ad04b9f4318049c01ebb52ef
    8aae4ac3694658cf90005dbdea37b4d5
    258fe6853b1bfb2d07f512ff6bec52b1

我已尝试通过 SED 过滤包含 Is a directory 的行,但未成功

md5deep find * | awk '{ print $1 }' | sed s/\/*//g

它的样本输出是

/Users/math/Documents/Articles/Number theory: Is a directory
/Users/math/Documents/Articles/Topology: Is a directory
/Users/math/Documents/Articles/useful: Is a directory

如何通过 SED/AWK 过滤掉包含“是目录”的每一行?

[澄清] 我想过滤掉包含 Is a directory 的行。

【问题讨论】:

    标签: sed awk


    【解决方案1】:

    我没有使用过md5deep 工具,但我相信这些行是错误消息;他们会去standard error而不是标准输出,所以他们会直接去你的终端而不是通过管道。因此,您的 sed 命令不会过滤它们。您可以通过合并标准错误和标准输出流来过滤它们,但是

    看起来(我不确定,因为您缺少反引号)您正在尝试调用

    md5deep `find *`
    

    find 正在返回所有文件和目录。

    关于您可能想要做的一些说明:

    • 看起来md5deep 有一个 -r 表示“递归”选项。所以,你可能想试试:

      md5deep -r *
      

      而不是 find 命令。

    • 如果您确实希望使用find 命令,您可以将其限制为仅使用-type f 的文件,而不是文件和目录。此外,您不需要将 * 传递给 find 命令(如果文件的名称看起来像 find 理解的选项,这可能会使 find 混淆);传入.会递归搜索当前目录。

      find . -type f
      
    • sed 中,如果你想在你的模式中使用斜线,用\ 正确引用它们可能会很痛苦。您可以改为选择不同的字符来分隔正则表达式; sed 将使用s 命令之后的第一个字符作为分隔符。您的模式也缺少.;在正则表达式中,要表示使用. 的任何字符的一个实例,并且要表示“前面的表达式的零个或多个”,则使用*,因此.* 表示“任何字符的零个或多个”(这与 glob 模式不同,其中 * 单独表示“任何字符的零个或多个”。

      sed "s|/.*||g"
      
    • 如果您确实想在标准输出中包含标准错误流,以便它通过管道,那么您可以运行:

      md5deep `find *` 2>&1 | awk ... 
      
    • 如果您只想忽略 stderr,可以将其重定向到 /dev/null,这是一个特殊文件,只会丢弃其中的任何内容:

      md5deep `find *` 2>/dev/null | awk ...
      

    总之,我认为下面的命令可以帮助您解决当前的问题,如果我没有理解您要查找的内容,上面列出的其他建议可能会对您有所帮助:

    md5deep -r * | awk '{ print $1 }'
    

    【讨论】:

    • 最后一个命令一直在运行——它永远不会结束。似乎 md5deep -r 不起作用。
    • 抱歉,看起来 md5deep 需要文件名参数;所以 md5deep -r * 应该可以工作。如果没有给出参数,它期待标准输入。
    • 你的最后一个命令有效! ---我对命令 md5deep find * 的错误是我没有使用 '.该命令将 sterr 和 stout 置于相同的输出。除了将 stout 和 sterr 保存到单独的文件之外,还有什么方法可以忽略 sterr?
    • 您可以通过使用 2>/dev/null 来忽略 stderr,例如在您的原始命令中使用“md5deep find * 2>/dev/null | awk ...”。
    • @Brian:我很惊讶:您的第一个命令的运行时间是 0.759 秒,而您的最后一个命令需要几分钟才能完成(仍在运行)。
    【解决方案2】:

    专门回答澄清:如何使用awk和sed过滤掉行:

    awk '/Is a directory/ {next} {print}'
    sed 'g/Is a directory/d'
    

    【讨论】:

    • 第一个命令有效。但是,最后一个没有。我也尝试了不带引号的命令,因为我觉得您在 Mac/Linux 中不需要这些引号。
    • 啊,对。我在想 ex 'g/re/d' 命令。对于 sed,您需要: sed '/Is a dir/d' (没有 'g') 是的,您确实需要引号将 sed 脚本作为单个参数传递给 sed 命令。
    【解决方案3】:

    为什么不改用 grep?

    即,

    md5deep find * | grep "Is a directory" | awk '{ print $1 }'
    

    编辑:我刚刚重新阅读了您的问题,如果您想删除带有 Is a directory 的行,请使用 grep 的 -v 标志,即:

    md5deep find * | grep -v "Is a directory" | awk '{ print $1 }'
    

    【讨论】:

    • 最后一个命令似乎有效。第一个问题是 stout 和 sterr 在同一个输出中。我需要将命令 1> hashes.txt 放在命令的末尾。似乎 md5deep 没有按预期工作 - 我只得到当前目录中文件的哈希值,而不是子目录中的文件。
    • 不需要使用 grep。 >>> md5deep 查找 * | awk '/是目录/{ print $1 }'
    【解决方案4】:

    我对 md5deep 不是很熟悉,但这可能会做一些你想做的事情。

    find -type f -exec md5sum {} +
    

    【讨论】:

      猜你喜欢
      • 2010-10-13
      • 1970-01-01
      • 2016-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-11
      • 1970-01-01
      相关资源
      最近更新 更多