Linux grep-o并使用ls显示部分文件名

Linux grep-o并使用ls显示部分文件名,linux,bash,shell,unix,awk,Linux,Bash,Shell,Unix,Awk,我有一个目录,其中有许多目录,其名称模式如下: YYYYDDMM_HHMISS 示例:20140102_120202 我只想提取YYYYDDMM部分。 我尝试了ls-l | awk'{print$9}'| grep-o^[0-9]*并得到了答案。 不过,我有以下问题: 为什么不返回任何结果:ls-l | awk'{print$9}'| grep-o[0-9]*。实际上,它应该返回所有目录。 奇怪的是,在[0-9]之前加上“^”就行了: ls-l | awk'{print$9}'| grep-o^

我有一个目录,其中有许多目录,其名称模式如下: YYYYDDMM_HHMISS 示例:20140102_120202 我只想提取YYYYDDMM部分。 我尝试了
ls-l | awk'{print$9}'| grep-o^[0-9]*
并得到了答案。 不过,我有以下问题:

  • 为什么不返回任何结果:
    ls-l | awk'{print$9}'| grep-o[0-9]*
    。实际上,它应该返回所有目录。 奇怪的是,在[0-9]之前加上“^”就行了:
    ls-l | awk'{print$9}'| grep-o^[0-9]*

  • 还有其他(更简单的)方法来达到这个结果吗


  • 必须避免解析
    ls
    输出

    使用此printf很简单:

    printf "%s\n" [0-9]*_[0-9]*|egrep -o '^[0-9]+'
    

    必须避免解析
    ls
    输出

    使用此printf很简单:

    printf "%s\n" [0-9]*_[0-9]*|egrep -o '^[0-9]+'
    
    为什么不返回任何结果:
    ls-l | awk'{print$9}'| grep-o[0-9]*

    如果当前目录中有以
    [0-9]
    开头的文件,那么shell将在调用
    grep
    之前展开它们。例如,如果我有两个文件
    a1
    a2
    a3
    ,并运行以下命令:

    ls | grep a*
    
    ls | grep a1 a2 a3
    
    文件名展开后,shell将运行以下操作:

    ls | grep a*
    
    ls | grep a1 a2 a3
    
    其结果是,它将打印
    a2
    a3
    中与文本“a1”匹配的行。它还将忽略来自stdin的任何内容,因为当您为
    grep
    (第二个参数及以上)指定文件名时,它将忽略stdin

    接下来,考虑一下:

    ls | grep ^a*
    
    在这里,
    ^
    对shell没有特殊意义,所以它一字不差地使用它。由于我没有以
    ^a
    开头的文件名,它将使用
    ^a*
    作为模式。如果我确实有像
    ^a方法
    ^a另一个
    这样的文件名,那么同样,
    ^a*
    将扩展到这些文件名,
    grep
    将执行我并不真正想要的操作

    这就是为什么必须引用搜索模式,以防止shell扩展它们。
    find/path-name'pattern'
    中的模式也是如此

    至于你想要的更简单的方法,我认为应该这样做:

    ls | sed -ne 's/_.*//p'
    
    为什么不返回任何结果:
    ls-l | awk'{print$9}'| grep-o[0-9]*

    如果当前目录中有以
    [0-9]
    开头的文件,那么shell将在调用
    grep
    之前展开它们。例如,如果我有两个文件
    a1
    a2
    a3
    ,并运行以下命令:

    ls | grep a*
    
    ls | grep a1 a2 a3
    
    文件名展开后,shell将运行以下操作:

    ls | grep a*
    
    ls | grep a1 a2 a3
    
    其结果是,它将打印
    a2
    a3
    中与文本“a1”匹配的行。它还将忽略来自stdin的任何内容,因为当您为
    grep
    (第二个参数及以上)指定文件名时,它将忽略stdin

    接下来,考虑一下:

    ls | grep ^a*
    
    在这里,
    ^
    对shell没有特殊意义,所以它一字不差地使用它。由于我没有以
    ^a
    开头的文件名,它将使用
    ^a*
    作为模式。如果我确实有像
    ^a方法
    ^a另一个
    这样的文件名,那么同样,
    ^a*
    将扩展到这些文件名,
    grep
    将执行我并不真正想要的操作

    这就是为什么必须引用搜索模式,以防止shell扩展它们。
    find/path-name'pattern'
    中的模式也是如此

    至于你想要的更简单的方法,我认为应该这样做:

    ls | sed -ne 's/_.*//p'
    

    要仅显示目录名的YYDDMM部分,请执行以下操作:

    for i in ./*; do echo $(basename "${i%%_*}"); done
    

    不确定一旦获得它,您想用它做什么…

    只显示目录名的YYDDMM部分:

    for i in ./*; do echo $(basename "${i%%_*}"); done
    

    不确定一旦你得到了它,你想用它做什么…

    原因是根本没有匹配,因为根本没有匹配,所以
    grep
    就到此为止。请尝试
    [0-9][0-9]*
    grep-E'[0-9]+'
    ,但如果没有锚,您也将匹配时间戳。请确保引用正则表达式,以防止shell尝试将其视为模式。如果shell成功,正则表达式将被替换为与之匹配的文件名列表。
    [0-9]*
    完全不匹配的原因是根本没有足够的匹配,因此
    grep
    在这里停止。请尝试
    [0-9][0-9]*
    grep-E'[0-9]+'
    ,但如果没有锚,您也将匹配时间戳。请确保引用正则表达式,以防止shell尝试将其视为模式。如果shell成功,正则表达式将被替换为与之匹配的文件名列表。是的,确实要干净得多。是的,确实要干净得多。