【问题标题】:Filtering a list of files with a perl one-liner使用 perl 单行过滤文件列表
【发布时间】:2021-11-03 13:53:32
【问题描述】:

我正在尝试使用 grep 的 -P 选项在命令行进行过滤,这应该是使用 perl 的正则表达式

ls | grep -P ZZZZZTYT.vcf.gz 有效

但是

ls | grep -P ZZZZZTYT.vcf.gz$

不起作用。对于 GNU grep 3.4,锚点似乎不适用于 grep -P

这些例子当然是微不足道的。

我也尝试过使用单行过滤器,例如 perl one-liner like grep?

ls | perl -ne 'print $1 if not $_ =~ m/\.gz$/'

但这也没有用。

ls | perl -ne 'print $1 if not /\.gz$/'

我的猜测是最好的选择是 perl one-liner。

如何重写上面的单行代码以在文件列表上进行 grep?

【问题讨论】:

  • @WiktorStribiżew 我不知道,文件名中有 CRLF 吗? ls | perl -ne 'print $_ if not /\.gz$/' 也失败了
  • @WiktorStribiżew dos2unix 打印出 dos2unix: Binary symbol 0x1F found at line 1 dos2unix: Skipping binary file ZZZZZTYT.vcf.gz 所以我的猜测是肯定的,这是按预期工作的。我在 Ubuntu 上
  • @WiktorStribiżew 不应该将文件名解释为字符串?
  • 对不起,我好像在这里搞糊涂了。我不明白为什么你现在应该看到这个问题。
  • Re "应该是用perl的正则表达式",不,应该是用PCRE

标签: perl grep


【解决方案1】:

尽管您的示例中存在一些问题,但我无法重现您的问题。

对于命令ls | grep -P ZZZZZTYT.vcf.gz 有效而ls | grep -P ZZZZZTYT.vcf.gz$ 无效,我的第一个猜测是您的文件末尾有空格或其他“不可见”字符。你可以试试ls | cat -A(或cat -veT)看看是否真的比你能看到的更多。无论如何,您的正则表达式可以更好地用文字点 (\.) 编写,因为 . 单独匹配任何内容。

在您的 perl onliners 中,您尝试打印 $1 并且此变量为空,来自 perldoc perlvar

$<digits> ($1, $2, ...)
     Contains the subpattern from the corresponding set of capturing
     parentheses from the last successful pattern match, not counting
     patterns matched in nested blocks that have been exited already.

     These variables are read-only and dynamically-scoped.

     Mnemonic: like \digits.

我想你想打印$_,当你使用-n开关时,这个变量保存当前行的内容(perlvar和perlfunc中的引用)。你可以将你的 perl oneliner 重写为:

ls | perl -ne'/\.gz$/ or print' # for not .gz files

ls | perl -ne'/\.gz$/ and print' # list .gz files

使用您的示例,从网上删除$1 就足够了。

如前所述,您需要检查文件名末尾是否有内容。

如果你的文件名和文件名中有“坏字符”,这个 oneliner 将适用于列出 .gz 文件:

ls | perl -ne'/\.gz.*$/ and print'

【讨论】:

  • 确实,这适用于.pl$,但不适用于.gz$
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-11
  • 1970-01-01
  • 2020-01-03
  • 2013-08-10
  • 2017-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多