[英]Replace string with output of command, different each time
I have many files and I want to replace the class names with a UUID. 我有很多文件,我想用UUID替换类名。 I figured out this
我想通了
sed -i -r "s/ Class \w(\w|\d)+/ Class C$(python -c 'import uuid;print(uuid.uuid4().hex)')/"
It works fine when the pattern only occurs once in each file. 当模式在每个文件中仅出现一次时,它可以正常工作。 However if the pattern occurs more than once, each occurence is replaced by the same number.
但是,如果模式多次出现,则每次出现都将替换为相同的数字。
Class1.vb Class1.vb
Public Class Class1
Public ReadOnly Property P As String = "hello"
End Class
Public Class Class2
Public ReadOnly Property P As String = "hello"
End Class
$ sed -r "s/ Class \w(\w|\d)+/ Class C$(echo $RANDOM)/" Class1.vb
Public Class C27244
Public ReadOnly Property P As String = "hello"
End Class
Public Class C27244
Public ReadOnly Property P As String = "hello"
End Class
I expect the two classes to have different names. 我希望两个类具有不同的名称。 How do I fix my script?
如何修复我的脚本?
$ awk '{gsub(/Class [[:alnum:]]+/, "Class C" int(9999*rand()))} 1' Class1.vb
Public Class C2377
Public ReadOnly Property P As String = "hello"
End Class
Public Class C5854
Public ReadOnly Property P As String = "hello"
End Class
The above will give you the same random numbers in the same order each time. 上面的代码会每次给您相同顺序的相同随机数。 If you want different random numbers each time you run the program, use:
如果每次运行该程序都需要不同的随机数,请使用:
awk -v s=$RANDOM 'BEGIN{srand(s)} {gsub(/Class [[:alnum:]]+/, "Class C" int(9999*rand()))} 1' Class1.vb
gsub(/Class [[:alnum:]]+/, "Class C" int(9999*rand()))
This looks for occurrences of the regex Class [[:alnum:]]+
and replaces each one with the concatenation of the string Class C
and a four-digit random number calculated from int(9999*rand())
. 这将查找正则表达式
Class [[:alnum:]]+
并用字符串Class C
和从int(9999*rand())
计算出的四位数随机数的连接替换每个正则表达式。 A new random number is generated for each line. 每行产生一个新的随机数。
1
This is awk's cryptic shorthand for print-the-current-line. 这是awk的“打印当前行”的隐喻速记。
More as a proof of concept than a serious alternative: a GNU sed solution. GNU sed解决方案更多是作为概念证明而不是严肃的选择。
sed -E -e '/Class \w+/{h;s/.*/bash -c "echo C\\$RANDOM"/;e' \
-e 'G;s/(.*)\n(.*Class )\w+(.*)/\2\1\3/}' infile
resulting in 导致
Public Class C24276
Public ReadOnly Property P As String = "hello"
End Class
Public Class C28554
Public ReadOnly Property P As String = "hello"
End Class
Here is how it works: 下面是它的工作原理:
/Class \w+/ { # If the line matches "Class <name>"
h # Copy pattern space to hold space
s/.*/bash -c "echo C\\$RANDOM"/ # Write Bash command into pattern space
e # Replace pattern space with command output
G # Append hold space to pattern space
s/(.*)\n(.*Class )\w+(.*)/\2\1\3/ # Swap class name with random number
}
Remarks: 备注:
\\w
character class and the e
command. \\w
字符类和e
命令。
\\w
includes digits , so there is no need for (\\w|\\d)
. \\w
包含数字 ,因此不需要(\\w|\\d)
。 -e
because the e
command cannot be followed by anything, or that anything is interpreted as the command. -e
将单行代码版本分为两个命令,因为e
命令后面不能有任何内容,或者任何内容都可以解释为该命令。 echo C$RANDOM
because the e
command uses sh
instead of Bash, and sh
might not have $RANDOM
(like on Ubuntu, where sh
is dash). echo C$RANDOM
因为e
命令使用sh
而不是Bash,并且sh
可能没有$RANDOM
(例如在Ubuntu上, sh
是破折号)。 Because the command is in double quotes, the $
in $RANDOM
has to be escaped, and because sed does a first pass before the shell sees the command, is has to be escaped twice. 由于该命令是在双引号中,
$
在$RANDOM
已经被转义,因为做的sed前壳第一遍看的命令,是已被转义两次。 Alternatively, I could have used 或者,我本可以使用
s/.*/bash -c '\\''echo C$RANDOM'\\''/
to single quote the command, but that's not very readable either. 用单引号将该命令引起来,但这也不是很容易理解。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.