我想用这样的值替换$SOME_TEXT_HERE$
这样的值:@some.text.here@
即:
- 将文本更改为小写
$
用。。。来代替@
- 将下划线替换为点
初始字符串中可能存在任意数量的不相关文本。可以替换任意数量的美元分隔文本。以美元分隔的文本可以由一个或多个大写单词组成,并用下划线分隔。
我知道如何执行步骤 1 和 2。我想知道如何将步骤 3 限制为美元符号内的内容。
好的,举个例子:
从:
Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$
到:
Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@
我已经做到了这一点:
echo 'Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$ ' |sed -e 's/\$\([A-Z]\+_\?\)\+\$/\L&/g' -e's/\$\(\([a-z]\+_\?\)\+\)\$/@\1@/g'
这使:
Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing_elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et_dolore_magna_aliqua@
不知道如何迭代匹配的组结果以获取 @ 符号中的所有单词。始终获取最后的匹配结果。
答案1
使用 Perl:
$ cat file
Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$
$ perl -pe 's/\$([[:upper:]_]+)\$/"@" . lc $1 =~ tr[_][.]r . "@"/eg' file
Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@
这里使用的 Perl 表达式是
s/\$([[:upper:]_]+)\$/"@" . lc $1 =~ tr[_][.]r . "@"/eg
这是一种应用于由首字母$
后跟一个或多个大写字符或下划线,后跟另一个$
字符组成的子字符串的替换。
$1
替换模式是一个 Perl 表达式,它使用运算符将与模式 () 中的括号组匹配的子字符串中的所有下划线更改为点tr
,然后使用 来将结果小写lc
。然后在结果@
前面和后面添加字符。
它是表达式/e
的标志s///
,使 Perl 将替换文本视为 Perl 表达式而不仅仅是文本。使用该标志对所有匹配重复替换/g
。
答案2
如果输入存储在shell$string
中的变量中zsh
,您可以执行以下操作:
set -o extendedglob
string=${string//(#b)\$([A-Z]##(_[A-Z]##)#)\$/@${(L)match[1]//_/.}@}
perl
与相同
string=$(
printf '%s\n' "$string" | perl -pe '
s{\$[A-Z]+(_[A-Z]+)*\$}{lc$& =~ y/_$/.@/r}ge'
)
或者:
string=$(
printf '%s\n' "$string" | perl -pe '
s{\$[A-Z]+(_[A-Z]+)*\$}{$& =~ y/A-Z_$/a-z.@/r}ge'
)
不同之处在于,它perl
在字节级别工作(在基于 ASCII 的系统上需要 ASCII 编码),而zsh
在字符级别工作(当字节无法解码为字符时,则回退到字节),具体取决于区域设置的编码。如果$string
以换行符结尾,则行为也会有所不同,因为命令替换会删除它们。
答案3
与 GNU sed
:(如你所愿sed
)
$ sed -E 's/\$([A-Z]+([A-Z]*_)*[A-Z]+)\$/@\L\1@/g;s/@([a-z]+)_/@\1./g;s/_([a-z]+)@/\.\1@/g; :X s/(\.[a-z]+)_/\1\./g; tX'
输出 :
$ echo 'Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$' | sed -E 's/\$([A-Z]+([A-Z]*_)*[A-Z]+)\$/@\L\1@/g;s/@([a-z]+)_/@\1./g;s/_([a-z]+)@/\.\1@/g; :X s/(\.[a-z]+)_/\1\./g; tX'
Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@
答案4
另一个稍微短一点的 GNUsed
sed -E "s/\\\$([A-Z_]+)\\\$/@\L\1@/g; :X s/(@[a-z.]+)_/\1./; tX" file
假设这@
不会在您的源中自然发生,并且$
仅在最初的情况下发生[A-Z_]
Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$
Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@
这对您的示例来说没问题,但如果您使用$BLAH_BLAH$blah_
->@blah.blah@blah.
而不是,则会失败@blah.blah@blah_
编辑重新 @Quasimodo 评论+
->*
在第二个sed
sed -E "s/\\\$([A-Z_]+)\\\$/@\L\1@/g; :X s/(@[a-z.]*)_/\1./; tX" file
Lorem $_IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$
Lorem @.ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@