【问题标题】:Extract text between two lines提取两行之间的文本
【发布时间】:2017-07-22 21:05:24
【问题描述】:

我正在构建一个bash 脚本,以使用figlist 可视化可用于figlet 的各种字体。

figlist 提供如下输出:

Default font: standard
Font directory: /usr/local/Cellar/figlet/2.2.5/share/figlet/fonts
Figlet fonts in this directory:
3-d
3x5
5lineoblique
[...]
twopoint
univers
usaflag
weird
whimsy
Figlet control files in this directory:
646-ca
646-ca2
646-cn
646-cu
[...]
tsalagi
upper
ushebrew
uskata
utf8

[...] 代表截断的输出。我想要的输出如下:

3-d
3x5
5lineoblique
[...]
twopoint
univers
usaflag
weird
whimsy

也就是说,我想要字体名称。我不能保证输出格式,但我不想要任何控制文件,也不想要信息行。我不确定,但我怀疑所有字体 必须 都有一个单词名称,因此可能有一个正则表达式解决方案。但是,控制文件具有类似的格式。

当前(硬编码)解决方案:

read -a fonts <<<$(figlist | tail -n +4 | head -n 163)

这提供了我想要的,但要求字体列表的长度永远不会改变,这是我想要的。

我更喜欢 bash/standard commands/builtins 中的解决方案,因为这是我编写脚本时使用的语言,但如果它可以通过 python 单线或类似的东西获得(例如python -c &lt;some command&gt;)那么这也是可以接受的。

【问题讨论】:

    标签: python bash awk sed figlet


    【解决方案1】:

    Python 单线

    figlist | python -c "import sys,re; fonts=re.search(r'Figlet fonts.+?:(.*)(?=Figlet control)',sys.stdin.read(), re.DOTALL); print(fonts.group(1).strip())"
    

    输出:

    3-d
    3x5
    5lineoblique
    [...]
    twopoint
    univers
    usaflag
    weird
    whimsy
    

    就是这样,伙计们

    【讨论】:

    • 谢谢分享,先生,你太棒了。你太擅长解决方案了:)
    • (1) 单行是适合一行的代码,而不是应该在多行但您将其压入一行的代码。 (2) 在 Python 中使用正则表达式不是正确的。使用String.startswith() 检查一个字符串是否以另一个固定字符串开头。
    • @hek2mgl,他通过 python 单线器问,我给了他单线器。没有你的建议,我知道str.startwith() 和正则表达式。所以,我不需要你的帮助
    • 虽然我倾向于同意 @hek2mgl 对 one-liner 的解释,但这 一个有效的解决方案,如果难以由于它的长度而表达。 +1 是一个很好的解决方案,但我更喜欢awk
    【解决方案2】:

    更新:

    更短的 preferable awk 替代方案是:

    figlist | awk '/Figlet/{p=!p;next}p'
    

    我建议使用下面的sed 命令。


    原答案:

    你可以使用sed:

    figlist | sed -n '/Figlet fonts/,/Figlet/{//!p;}'
    

    例子:

    使用每个安装的 figlet 字体打印当前用户名:

    figlist \
      | sed -n '/Figlet fonts/,/Figlet/{//!p;}' \
      | while read -r font ; do
            echo "font: ${font}"
            figlet -f"${font}" "$(whoami)"
        done
    

    【讨论】:

    • 感谢您的快速回复。我在 bash 中以交互方式获取 sed: 1: "/Figlet fonts/,/Figlet/ ...": extra characters at the end of p command
    • 看起来您使用的是 Mac。在p 之后添加;。编辑了答案中的代码。
    • @EdMorton 我同意awk 解决方案由于您提到的原因更可取。我从来不知道当一行中的最后一个符号是管道时,bash 中的命令可以跨越多行。我仍然喜欢在线条的开头对齐管道。 Imo 这更容易阅读。 (而且看起来不错;))
    • 这绝对是旁观者的眼睛——我更喜欢管道的外观(如果有意义,对齐)在行的末尾和管道中涉及的命令在行的开头对齐。恕我直言,它使每一行都更加清晰,因为您可以在每一行上单独看到它的输出将进入管道(而不是被重定向到文件或任何其他可能跟随反斜杠的内容)。本质上,这意味着您无需阅读下一行即可完全了解当前行在做什么。而且它节省了几个字符,并且不会影响您的正常缩进!虽然 nbd...
    • @EdMorton 可以避免重复条件:sed -n '/^Figlet fonts/,/^Figlet/{//!p;}'
    【解决方案3】:

    由于这个问题也被标记为 ,我随时添加一个 awk 解决方案:

    /^Figlet fonts/ { on = 1 ; next }
    /^Figlet control/ { on = 0 ; next }
    on { print $0 }
    

    测试(在 bash、cygwin、Windows 10 上):

    $ echo 'Default font: standard
    > Font directory: /usr/local/Cellar/figlet/2.2.5/share/figlet/fonts
    > Figlet fonts in this directory:
    > 3-d
    > 3x5
    > 5lineoblique
    > [...]
    > twopoint
    > univers
    > usaflag
    > weird
    > whimsy
    > Figlet control files in this directory:
    > 646-ca
    > 646-ca2
    > 646-cn
    > 646-cu
    > [...]
    > tsalagi
    > upper
    > ushebrew
    > uskata
    > utf8
    > ' | awk '/^Figlet fonts/ { on = 1 ; next } /^Figlet control/ { on = 0 ; next } on { print $0 }'
    3-d
    3x5
    5lineoblique
    [...]
    twopoint
    univers
    usaflag
    weird
    whimsy
    
    $
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-02
      • 1970-01-01
      • 1970-01-01
      • 2011-12-31
      • 2019-07-02
      • 1970-01-01
      相关资源
      最近更新 更多