我有一个 form 字符串FOO_123_BAR.bazquux,其中FOO和BAR是固定字符串,123是一个数字并且bazquux是自由格式的文本。
我需要对这个字符串执行文本转换:提取123和bazquux,增加数字,然后将它们排列在不同的字符串中。
例如,FOO_123_BAR.bazquux? FOO=124 BAR=bazquux. (实际转换更复杂。)
自然地,我可以在一系列 sed 和 expr 调用中做到这一点,但它很难看:
shopt -s lastpipe
in=FOO_123_BAR.bazquux
echo "$in" | sed -r 's|^FOO_([0-9]+)_BAR\.(.+)$|\1 \2|' | read number text
out="FOO=$((number + 1)) BAR=$text"
Run Code Online (Sandbox Code Playgroud)
是否有更强大的文本处理工具可以在一次调用中完成这项工作?如果是,那么如何?
编辑:我很抱歉没有更清楚地说明这一点,但输入和输出的确切结构是一个例子。因此,我更喜欢使用任何分隔符或不存在分隔符的通用解决方案,而不是依赖于例如存在下划线的解决方案。
使用GNU sed,您可以使用e标志将整个替换字符串作为外部命令执行。
$ s='FOO_123_BAR.bazquux'
$ echo "$s" | sed -E 's/^FOO_([0-9]+)_BAR\.(.+)$/echo FOO=$((\1 + 1)) BAR=\2/e'
FOO=124 BAR=bazquux
Run Code Online (Sandbox Code Playgroud)
为避免与 shell 元字符冲突,您需要引用未知部分:
$ s='FOO_123_BAR.$x(1)'
$ echo "$s" | sed -E 's/^FOO_([0-9]+)_BAR\.(.+)$/echo FOO=$((\1 + 1)) BAR=\2/e'
sh: 1: Syntax error: "(" unexpected
$ echo "$s" | sed -E 's/^FOO_([0-9]+)_BAR\.(.+)$/echo FOO=$((\1 + 1)) BAR=\x27\2\x27/e'
FOO=124 BAR=$x(1)
Run Code Online (Sandbox Code Playgroud)
在每个 UNIX 机器上的任何 shell 中使用任何 awk 并假设您的子字符串都不包含_或.:
$ s='FOO_123_BAR.bazquux'
$ echo "$s" | awk -F'[_.]' '{print $1"="$2+1,$3"="$4}'
FOO=124 BAR=bazquux
Run Code Online (Sandbox Code Playgroud)