我有一些文件驻留在 Linux 系统上,其中包含一些占位符,例如下面的文件:
测试.txt:
This is a line with <VARIABLE1>@<VARIABLE2>.
This is a line with <VARIABLE3>.
This is a line with <VARIABLE_UNKNOWN>.
This is another line contains a<b.
我想更改此文件,如下所示:
This is a test line with $VARIABLE1@$VARIABLE2.
This is a test line with $VARIABLE3.
This is a test line with $VARIABLE_UNKNOWN.
This is another line contains a<b.
请注意,所有这些以 结尾的变量<>
仅包含大写字母、数字和下划线。
我本可以使用以下方法,但a<b
变成了a$b
。
file_contents=$(<$file_path)
file_contents=${file_contents//</$}
file_contents=$(echo "$file_contents" | tr -d '>')
echo "$file_contents" > test.txt
我试图避免sed
使用变得非常难以调试的复杂命令。我怎样才能实现这个目标?
如果问题可以表述为“我想转换所有包含在其中
< >
且仅由一个或多个大写字母、数字和下划线组成的字符串,这些字符串包含在它们< >
自身中,但用 a$
代替< >
”,那么您可以这样做:这
-pe
意味着“逐行读取输入文件,应用给出的脚本-e
,然后打印每一行”。然后,我们将替换运算符 (s/OLD/NEW/
) 与g
标志一起使用,以便它替换该行中的所有匹配项。最后,正则表达式查找<
后跟一个或多个(指+
一个或多个)大写 ASCII 字母 (A-Z
)、ASCII1 十进制数字 (\d
) 或_
以 结尾的下划线 ( )>
。现在,因为模式位于括号 ( ) 中,所以我们已“捕获”它并可以在替换中([A-Z\d_]+)
引用它。$1
因此,我们将匹配的内容替换为 a$
(需要转义为\$
),然后替换匹配的内容:\$$1
。至少只要
$PERL_UNICODE
未设置环境变量,在这种情况下它就可以匹配其他类型的十进制数字。使用该a
标志给s///
操作符保证只有0123456789被匹配,或者替换\d
为0-9
or0123456789
由于这是对各行的简单替换,因此执行此操作的 sed 命令并不复杂:
或者如果您的 sed 没有
-E
任何 POSIX sed:如果您的 sed 甚至不兼容 POSIX,那么请获取一个新的,但对于这一特定的事情您可能会这样做:
正如@chrisdavies 指出的那样,这可能不是您真正应该尝试获得的输出,因为它会变成,
<VAR1>27
您$VAR127
应该真正瞄准其中任何一个:取决于您计划如何处理该输出。
FWIW 通常,当人们在文本中包含占位符字符串时,他们不会将其替换为shell 变量的名称,而是将其替换为shell 变量的内容,否则当您可以刚刚创建文本时,在文本中使用占位符有什么意义首先使用 shell 变量名称?
使用Raku(以前称为 Perl_6)
再说一遍,这几乎是 @terdon 优秀 Perl 答案的直接翻译。
在乐,
g
lobal)位于匹配器的开头,前面带有冒号,以给出s:g///
“替代全局”形式。<[ ... ]>
在识别域内,使用尖括号包围的方括号创建自定义字符类。方括号单独用于将正则表达式原子和/或属性分组在一起(参见底部的示例)。..
双点指定,如 (例如)A..Z
或0..9
。\<
。\>
$0
并且必须在替换域中使用。{...}
在替换域中使用代码块,以便可以编写上述替换{"\$$0"}
(即内插字符串)。对于在输出中执行简单的数学运算(求和等)非常有用。输入示例:
示例输出:
最后,@terdon 很好地概述了所有正则表达式系统的问题,因此需要准确理解 digital 的含义,即这些数字是 ASCII 数字还是 Unicode 数字?
Raku 以其成为“Unicode 就绪”语言而自豪,您可以在底部的第一个链接中找到用于 Raku 正则表达式的 Unicode 字符类的广泛列表。因此,在 Raku 中,
\d
数字简写包括 Unicode 数字。您可以按照上面的方式枚举数字,或者使用字符类与连词组合将数字0..9
子集/限制\d
为 ASCII 数字,如下所示:<:ASCII>
&&
[<:ASCII> && \d]
上面
<:Lu>
是“Letters-uppercase”的 Unicode 字符类。如果需要,<:ASCII>
可以使用相同的技巧来子集为“ASCII 字母大写”(或更简单地,重新排列上面的方括号以重新组合)。https://docs.raku.org/language/regexes#Unicode_properties
https://www.unicode.org/terminology/digits.html
https://docs.raku.org/language/regexes#Conjunction:_&&
https:// /docs.raku.org/language/regexes
https://raku.org
使用
gawk
:在 gensub() 函数中,可以使用括号 as 来记忆子模式,并在稍后使用as
captured group
引用它。backreference
\n
来自
GNU awk
手册: