答案1
使用乐(以前称为 Perl_6)
Raku 是 Perl 编程语言家族中的一种编程语言。我发布此答案是为了强调 Raku 易于阅读的:nth()
正则表达式修饰符,它也可以写成:1st
、:2nd
、:3rd
、:4th
等。
使用S///
运算符:
~$ raku -e 'given slurp() { put S:nth(6)/ line /|*-> line <-*|/ };' file
#OR
~$ raku -e 'given slurp() { put S:6th/ line /|*-> line <-*|/ };' file
使用subst()
运算符:
~$ raku -e 'put slurp.subst: :nth(6), /line/, "|*-> line <-*|";' file
#OR
~$ raku -e 'put slurp.subst: :6th, /line/, "|*-> line <-*|";' file
输入示例:
1st line Doc
2nd line Sneezy
3rd line Grumpy
4th line Happy
5th line Bashful
6th line Sleepy
7th line Dopey
示例输出(所有代码示例):
1st line Doc
2nd line Sneezy
3rd line Grumpy
4th line Happy
5th line Bashful
6th |*-> line <-*| Sleepy
7th line Dopey
https://docs.raku.org/language/regexes#Positional_adverbs
https://docs.raku.org/routine/subst
https://raku.org
答案2
在尝试解决方案之前,让我们首先分析问题所在。这是你的命令:
sed -i 's/TRACK 02/TRACK 03/2' *cue
我不会使用 sed 的 -i 选项,但这是次要问题。sed
致力于线,而不是带有文本和正则表达式(如“TRACK 02”)的文件描述了线,不是文件。你的命令说的是:
如果一行包含字符串“TRACK 02”两次(或更频繁),则将第二次出现的字符串更改为“TRACK 03”。像这样:
曲目02曲目02轨道 02 轨道 02 [...] ==>
轨道 02曲目03曲目 02 曲目 02 [...]
另请注意,正则表达式(或者更确切地说,底层常规语法根据定义,它们是上下文无关的。因此,您可以做的事情存在一些限制。了解更多信息这是初学者,如果您有兴趣我建议您阅读“Dragon book”(Aho、Sethi 和 Ullman 的《编译器:原理、技术和工具》)进行更深入的分析。
您需要了解的另一件事是 sed 的工作原理:它读取要更改的文本的第一行,然后应用第一个命令,根据结果应用第二个命令,依此类推,直到到达最后一个命令。如果不使用 -n 选项,则打印结果,读入下一行,应用第一个命令,等等,直到最后一个命令应用到最后一行倒数第二个命令的结果- sed 停止。
这就是为什么你不能这样做:
s/TRACK 00/TRACK 01/
s/TRACK 01/TRACK 02/
s/TRACK 02/TRACK 03/
s/TRACK 03/TRACK 04/
这会将“00”更改为“01”,下一个命令会将“01”更改为“02”,下一个“02”更改为“03”,依此类推。最后,所有行都将显示为“TRACK 04”(或者无论您想要列表多长)。
然而,您可以做的是反向进行更改(如果您有超过 10 个标题,请在开头添加类似的行)。当我们这样做时,我们还可以自动添加预间隙TRACK 01:
sed 's/TRACK 09/TRACK 10/
s/TRACK 08/TRACK 09/
s/TRACK 07/TRACK 08/
s/TRACK 06/TRACK 07/
s/TRACK 05/TRACK 06/
s/TRACK 04/TRACK 05/
s/TRACK 03/TRACK 04/
s/TRACK 02/TRACK 03/
s/TRACK 01/TRACK 02/
/FILE/ { a\
TRACK 01
a\
addtional optional text under TRACK 01
}' /path/to/file
最后,这里建议如何使用这个 sed 脚本进行大规模更改。我们将更改后的文件放在其他目录中,而保留原始文件。如果 (除非)我们检查了结果并对结果感到满意,我们将其复制回来覆盖原始结果:
for fWork in "*cue" ; do
sed 'the script from above' "$fWork" > "/other/path/$fWork"
done
现在,去检查结果。如果你喜欢的话:
mv /other/path/*cur /original/path