如何在 Linux 和 Mac 之间使用跨平台/标准 sed?

如何在 Linux 和 Mac 之间使用跨平台/标准 sed?

您好,我有一个脚本在 makefile 中运行以进行项目部署。我在其中使用 sed 从输入字符串中捕获环境和项目名称,并且在 ubuntu 中效果很好。

这个简单的命令

 echo deploy-api-production | sed -E 's/deploy-\w+-(\w+)/\1/'

production在 ubuntu 中给出了预期结果

ubuntu执行

$  echo deploy-api-production | sed -E 's/deploy-\w+-(\w+)/\1/'
production

但在 mac 中给出了整个完整的字符串deploy-api-production

mac执行:

$  echo deploy-api-production | sed -E 's/deploy-\w+-(\w+)/\1/'
deploy-api-production

是否有某种统一的 sed 以便我在 mac 中也能得到相同的结果?

我希望输出也只是 mac 执行中的生产

情况 2 - 更通用,也包括前缀

想要正确解析这个

echo a-deploy-api-production | someprocessing
production

so 与上面的情况类似,但是a-在该单词之前多了一个前缀单词deploy

我尝试了类似于当前给定解决方案的方法,但没有成功

echo a-deploy-api-production | awk -F'-' '$1=="a-deploy"{print $3}'

上面的结果为空,想要修改以获得结果production

答案1

您可以使用awk

echo deploy-api-production | awk -F'-' '$1=="deploy"{print $3}'

这会将文本分割成由 分隔的部分-。它要求第一个字段与单词匹配deploy,然后打印第三个字段。

在您更新的问题中,您包含了一个新的变体。您不能使用相同的awk代码直接比较,a-deploy因为这是两个字段(请记住,它们被破折号分隔),并且$1只是第一个字段(即,a而不是deploy在这个新实例中)。

在不了解所有用例的情况下,我建议您可能更乐意搜索deploy字符串中的任何位置,如果找到,则打印最后一个字段。 (这也适用于您的原始案例。)

echo deploy-api-production | awk -F'-' '/deploy/ {print $NF}'
production

echo a-deploy-api-production | awk -F'-' '/deploy/ {print $NF}'
production

答案2

使用 POSIX- sed,两种场景都可以获得所需的结果,如图所示:

w='[[:alpha:]][_[:alnum:]]*'
echo 'deploy-api-productionN' | 
sed -n -e "/^\($w-\)\{0,1\}deploy-/s/^$w\(-\($w\)\)\{1,\}\$/\2/p"

观察结果:

  • 由于 sed 没有单词的符号,我们将为它构建一个正则表达式并将它们存储在 shell 变量中$w
  • \{0,1\} 是 BRE 的 ?
  • \{1,\} 是 + 的 BRE
  • \(...\) 是 (...) 的 BRE

答案3

您在两个系统上得到不同的结果,因为 GNU 系统使用正则表达式库,该库已扩展为包含来自称为PCRE(Perl 兼容的正则表达式)。这些符号(如\s\w)不是标准符号,并且不受sed所有系统支持(通常不在 GNU 系统之外)。

-如果行以子字符串deploy或开头,您似乎想在最后一个(破折号)之后输出行的最后一部分something-deploy

您可以使用标准方法来做到这sed一点

sed '/^deploy/ s/.*-//'

或与

sed '/^something-deploy/ s/.*-//'

如果前面的正则表达式与当前输入行匹配,这些sed表达式将触发替换。s/.*-//此替换会删除该行中直到并包括最后一个破折号的所有内容。

在这种情况下,如果需要,可以将触发表达式与替换结合起来:

sed 's/^deploy.*-//'
sed 's/^something-deploy.*-//'

如果您的数据不是由echo(如问题中所示)输出的静态字符串,而是变量中的某个值,那么让 shell 执行此操作而不是调用外部程序会更有效:

string=deploy-api-production

if [[ $string == deploy-* ]]; then
    printf '%s\n' "${string##*-}"
fi

您将使用变量赋值,而不是printf如果您想保留修改后的值,如 中所示new=${string##*-}

扩展将从与 shell 模式匹配的${variable##pattern}最长前缀字符串中删除。$variablepattern

相关内容