【问题标题】:Extract bin name from Cargo.toml using Bash使用 Bash 从 Cargo.toml 中提取 bin 名称
【发布时间】:2021-11-12 03:33:10
【问题描述】:

我正在尝试使用 Bash 从 Cargo.toml 中提取 bin 名称,我启用了这样的 perl 正则表达式

第一次尝试

grep -Pzo '(?<=(^\[\[bin\]\]))\s*name\s*=\s*"(.*)"' ./Cargo.toml

正则表达式在regex101进行测试 但一无所获

Pzo 选项的用法可以参考here

第二次尝试

grep -P (?name\s=\s*"(.*)" ./Cargo.toml

什么都没有

grep -Pzo '(?<=(^\[\[bin\]\]))\s*name\s*=\s*"(.*)"' ./Cargo.toml

Cargo.toml

[[bin]]
name = "acme1"
path = "bin/acme1.rs"

[[bin]]
name = "acme2"
path = "src/acme1.rs"

【问题讨论】:

  • 既然这是标记为 rust,为什么不编写一个只解析文件(使用crates.io/crates/toml)并输出名称的小二进制文件? ;-)

标签: grep toml


【解决方案1】:

grep:

grep -A1 '^\[\[bin\]\]$' |
grep -Po '(?<=^name = ")[^"]*(?=".*)'

或者如果你可以使用 awk,这会更健壮

awk '
$1 ~ /^\[\[?[[:alnum:]]*\]\]?$/{
    if ($1=="[[bin]]" || $1=="[bin]") {bin=1}
    else {bin=0}
}
bin==1 &&
sub(/^[[:space:]]*name[[:space:]]*=[[:space:]]*/, "") {
    sub(/^"/, ""); sub(/".*$/, "")
    print
}' cargo.toml

例子:

$ cat cargo.toml
[[bin]]
name = "acme1"
path = "bin/acme1.rs"

[bin]
name="acme2"

[[foo]]
name = "nobin"

    [bin]
not_name = "hello"
name="acme3"
path = "src/acme3.rs"

[[bin]]
path = "bin/acme4.rs"
name = "acme4" # a comment

$ sh solution
acme1
acme2
acme3
acme4

显然,这些不能替代真正的 toml 解析器。

【讨论】:

    【解决方案2】:

    根据您展示的示例和尝试,请尝试使用tac + awk 组合的以下代码,这将更容易维护和轻松完成工作,这在grep 中会很困难。

    tac Input_file | 
    awk '
      /^name =/{
        gsub(/"/,"",$NF)
        value=$NF
        next
      }
      /^path[[:space:]]+=[[:space:]]+"bin\//{
        print value
        value=""
      }
    ' | 
    tac
    

    说明:为上述代码添加详细说明。

    tac Input_file |                             ##Using tac command on Input_file to print it in bottom to top order.
    awk '                                        ##passing tac output to awk as standard input.
      /^name =/{                                 ##Checking if line starts from name = then do following.
        gsub(/"/,"",$NF)                         ##Globally substituting " with NULL in last field.
        value=$NF                                ##Setting value to last field value here.
        next                                     ##next will skip all further statements from here.
      }
      /^path[[:space:]]+=[[:space:]]+"bin\//{    ##Checking if line starts from path followed by space = followed by spaces followed by "bin/ here.
        print value                              ##printing value here.
        value=""                                 ##Nullifying value here.
      }
    ' |                                          ##Passing awk program output as input to tac here. 
    tac                                          ##Printing values in their actual order.
    

    【讨论】:

    • 感谢您的详细解释,我还需要排除不在 [[bin]] 下的名称。
    猜你喜欢
    • 2016-03-07
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    • 1970-01-01
    • 1970-01-01
    • 2018-07-27
    • 2020-06-26
    • 2012-05-22
    相关资源
    最近更新 更多