【问题标题】:Iterate through a file until match and find a second, different match, until no match. Repeat until EOF遍历文件直到匹配并找到第二个不同的匹配,直到没有匹配。重复直到EOF
【发布时间】:2016-04-28 07:18:55
【问题描述】:

您好,我正在运行的 salt 脚本有一个相当大但混乱的输出。

基本上我最干净的输出如下所示:

MINION:server1.xyz.com
MINION:server2.xyz.com
MINION:server3.xyz.com
filer1:/vol/storagestuffs/volpath1
filer1:/vol/storagestuffs/volpath2
filer1:/vol/storagestuffs/volpath3
filer1:/vol/storagestuffs/volpath4
MINION:server4.xyz.com
filer4:/vol/storagestuffs/volpath1
MINION:server5.xyz.com
MINION:server6.xyz.com
MINION:server7.xyz.com
filer3:/vol/storagestuffs/volpath1

我想要的只是返回下面有文件管理器的仆从以及它们下面的所有文件管理器,我希望将其格式化为:

MINION:server3.xyz.com filer1:/vol/storagestuffs/volpath1 
MINION:server3.xyz.com filer1:/vol/storagestuffs/volpath2
MINION:server3.xyz.com filer1:/vol/storagestuffs/volpath3
MINION:server3.xyz.com filer1:/vol/storagestuffs/volpath4
MINION:server4.xyz.com filer4:/vol/storagestuffs/volpath1
MINION:server7.xyz.com filer3:/vol/storagestuffs/volpath1

我研究了 if 语句、递归语句等。我要么无法理解 bash 递归语句,要么这不是我想要做的。我希望找到一种有效的方法来执行此操作,而无需多次扫描文件。

有没有使用 xargs 的棘手方法? grep 中有什么可以做到这一点吗?

感谢您的帮助!

【问题讨论】:

    标签: bash if-statement recursion grep xargs


    【解决方案1】:

    只有 Bash 的解决方案是:

    minions_with_filers () 
    { 
        label=;
        while IFS=: read -r a b; do
            case $a in 
                MINION)
                    label=$a:$b
                ;;
                filer[0-9]*)
                    printf '%s %s:%s\n' "$label" "$a" "$b"
                ;;
            esac
        done
    }
    

    不过,@anubhava 的解决方案的运行速度会快 10 倍左右。

    用法示例:

    $ minions_with_filers < foo.txt 
    MINION:server3.xyz.com filer1:/vol/storagestuffs/volpath1
    MINION:server3.xyz.com filer1:/vol/storagestuffs/volpath2
    MINION:server3.xyz.com filer1:/vol/storagestuffs/volpath3
    MINION:server3.xyz.com filer1:/vol/storagestuffs/volpath4
    MINION:server4.xyz.com filer4:/vol/storagestuffs/volpath1
    MINION:server7.xyz.com filer3:/vol/storagestuffs/volpath1
    

    【讨论】:

      【解决方案2】:

      你可以使用awk:

      awk '/^MINION:/{m=$0} /^filer/{print m, $0}' file
      MINION:server3.xyz.com filer1:/vol/storagestuffs/volpath1
      MINION:server3.xyz.com filer1:/vol/storagestuffs/volpath2
      MINION:server3.xyz.com filer1:/vol/storagestuffs/volpath3
      MINION:server3.xyz.com filer1:/vol/storagestuffs/volpath4
      MINION:server4.xyz.com filer4:/vol/storagestuffs/volpath1
      MINION:server7.xyz.com filer3:/vol/storagestuffs/volpath1
      

      【讨论】:

      • 是否允许“filer”行总是紧跟在 MINION 行(或其他“filer”行)之前?如果是这样的话,anubhava 的脚本非常优雅——否则在其他情况下它会失败——尽管这在 awk 中也很容易修复。
      • @DirkHerrmann:如果 MINIONfiler 行之间有一些随机行,这个 awk 仍然可以工作
      • 行得通!你能解释一下这里发生了什么吗?我似乎永远无法达到 awk 的能力……
      • /^MINION:/{m=$0} 将当前行存储在变量m 中,如果行以MINION 开头。然后/^filer/{print m, $0} 打印m 和当前行,当该行以filer 开头时
      • 不知何故这奏效了:awk '/^MINION:/{m=$0} m && /^[filer|denfiler]/{print m, $0}'
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-12
      • 2017-04-08
      • 2017-12-22
      • 2018-01-02
      相关资源
      最近更新 更多