【问题标题】:Escaping in a Bash extended pattern @(..)在 Bash 扩展模式中转义 @(..)
【发布时间】:2017-03-10 13:51:47
【问题描述】:

我偶然发现了 Bash 的“扩展模式”extglob。 http://wiki.bash-hackers.org/syntax/pattern

我正在调查此案:

想象一下这样的目录结构:

/basedir/2017/02/26/uniquedirs1/files.log 
/basedir/2017/02/27/uniquedirs2/files.log 
/basedir/2017/02/28/uniquedirs3/files.log 
/basedir/2017/03/01/uniquedirs4/files.log
/basedir/2017/03/02/uniquedirs5/files.log

如果我想列出目录2017/02/272017/02/28 的文件,我可以简单地写:

ls /basedir/2017/02/@("27"|"28")/*/files.log

太棒了! \o/

现在是问题。如何在 Bash 扩展模式中定义多个目录?
这不起作用:

ls /basedir/2017/@("02/28"|"03/01")/*/files.log
ls /basedir/2017/@("02\/28"|"03\/01")/*/files.log

有什么方法可以为“扩展模式”定义多个目录?

【问题讨论】:

    标签: regex bash pattern-matching glob


    【解决方案1】:

    路径名生成仅将模式应用于路径名组件;它们从不匹配分隔组件的/。大括号扩展在这里会更干净:

    ls /basedir/2017/{2/28,3/01}/*/files.log
    

    首先展开为

    ls /basedir/2017/2/28/*/files.log /basedir/2017/3/01/*/files.log
    

    在对两个结果模式执行路径名生成之前。

    【讨论】:

    • 大括号扩展的唯一问题是我无法动态定义范围。
    • 你也不能使用扩展模式,所以你不会丢失任何东西:)
    • 好的。真可惜......我仍然没有接近有效的解决方案。我唯一的问题是不能动态定义大括号扩展。就像var1="02/28,03/01" ls /basedir/2017/"$var1"/*/files.log 一样,除非我在子shell 中执行它。但这有效:var2="27|28" ls /basedir/2017/02/@("$var2")/*/files.log
    【解决方案2】:

    好的,我动态解决这个问题的方式是这样的:

    #!/bin/bash
    # User input:
    start_date="2017-02-27"
    day_range=2
    
    # Logic:
    
    declare -a 'date_range=($( echo {'"$day_range"'..0} | xargs -I{} -d " " date -d "'"$start_date"' +{} day" --rfc-3339="date" ))'
    #this creates an array with dates:
    #2017-03-02 2017-03-01 2017-02-28 2017-02-27
    
    eval ls "basedir/{$(IFS=\, ; echo "${date_range[*]//-//}")}/*/files.log"
    #this translates to:
    #ls basedir/{2017/03/01,2017/02/28,2017/02/27}/*/files.log
    

    如果您想在无法使用文件创建日期的情况下将其与 grep 等工具一起使用以获取数据,这将更加有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-11
      • 2013-03-18
      • 1970-01-01
      • 1970-01-01
      • 2019-03-05
      • 1970-01-01
      相关资源
      最近更新 更多