嗨,我创建了一个大型的命令集来操作文本文件。最后一件我似乎无法解决的事情是,一行只是由一对()组成
some text
()
more text
(leave this line as is)我想删除整个()行
some text
more text
(leave this line as is)在我的脚本中,sed命令-e '/ () / s/()//'可以找到并删除(),但留下一行
some text
more text
(leave this line as is)下面是大图的剪短版
FILEPATH=*.chordpro
for fn in $FILEPATH; do
echo $fn
fnbak=$fn.bak
mv "$fn" "$fnbak" #Create an untouched backup
sed `: # these are comments` \
`: # Insert after subtitle; author,book,keywords,tempo,time` \
-e '/^{subtitle.*/a {author:mds}\n{book:CatStevens}\n{keywords:70s,Tillerman}\n{tempo:120}\n{time:4/4}' \
-e 's/{subtitle:/{artist:/' `: # swap subtitle for artist` \
-e 's/{time:/{duration:/' `: # modifiy original meta "time" for "duration"` \
....lots of other commands
`: # Tidy up` \
-e '/()/ s/()//' `: # Remove any () pairs created by script` \
"$fnbak" >"$fn"下面是输入测试用例的片段。
{c:Verse2}
{c: Verse 2: Bass single}
{c: Verse 2 Rock it}
{c: verse 1}
{c: verse 1}
{c: Verse 1:}
{c:Verse}在这里,它被转换了。Out#1
Verse 2:
()
Verse 2:
( Bass single)
Verse 2:
( Rock it)
Verse 1:
()
Verse 1:
()
Verse 1:
()
Verse :
()这是使用-e '/()/ s/()//' Out#2进行整理的结果
Verse 2:
Verse 2:
( Bass single)
Verse 2:
( Rock it)
Verse 1:
Verse 1:
Verse 1:
Verse :这是使用-e '/()/d'的结果。
Verse 2:
( Bass single)
Verse 2:
( Rock it),在Rock之后,所有东西都在哪里?注意:好的,这与它在循环中/与其他sed命令的交互有关。如果我将Out#1单独放入文件中,并仅在文件上运行sed -e '/()/d'命令,它就能工作。
这就是我希望达到的目标。
Verse 2:
Verse 2:
( Bass single)
Verse 2:
( Rock it)
Verse 1:
Verse 1:
Verse 1:
Verse :发布于 2020-06-28 12:14:25
不要编写冗长的sed脚本,而要使用awk来提高清晰度、效率、健壮性、可移植性等。
sed `: # these are comments` \
`: # Insert after subtitle; author,book,keywords,tempo,time` \
-e '/^{subtitle.*/a {author:mds}\n{book:CatStevens}\n{keywords:70s,Tillerman}\n{tempo:120}\n{time:4/4}' \
-e 's/{subtitle:/{artist:/' `: # swap subtitle for artist` \
-e 's/{time:/{duration:/' `: # modifiy original meta "time" for "duration"` \
....lots of other commands
`: # Tidy up` \
-e '/()/ s/()//' `: # Remove any () pairs created by script` \
"$fnbak" >"$fn"尝试一下,我认为相当于上面所做的,但也修正了您的代码以删除()对:
awk '
# Insert after subtitle; author,book,keywords,tempo,time
/^{subtitle/ {
$0 = $0 \
"\n{author:mds}" \
"\n{book:CatStevens}" \
"\n{keywords:70s,Tillerman}" \
"\n{tempo:120}" \
"\n{time:4/4}"
}
{
sub(/{subtitle:/,"{artist:") # swap subtitle for artist
sub/{time:/,"{duration:") # modify original meta "time" for "duration"
....lots of other commands
# Tidy up
# Remove any () pairs created by script
gsub(/\n\()\n/,"\n") # Convert every \n()\n to \n ..
gsub(/\n\()\n/,"\n") # .. done twice to handle \n()\n()\n
gsub(/^\()\n|\n\()$/,"") # Remove ()\n at the start and \n() at the end
gsub(/\()/,"") # Remove every remaining ()
print
}
' "$fnbak" > "$fn"您的评论说是Remove any () pairs created by script,但是您发布的脚本不能创建任何()对,所以我假设您的lots of other commands可以这样做,我只是在我的awk脚本中猜测您真正想要在"Tidy“部分做什么,因为您没有提供任何我们可以测试的示例输入/输出。
顺便说一句,修改输入文件的更常见的方法是:
fnbak=$(mktemp) || exit 1
cmd 'script' "$fn" > "$fnbak" &&
mv -- "$fnbak" "$fn"而不是
fnbak=$fn.bak
mv "$fn" "$fnback"
cmd 'script' "$fnbak" > "$fn"前者只保留备份文件足够长的时间来修改原始文件,只对所有文件使用一个备份,而不是对每个文件使用一个备份,如果没有足够的磁盘空间或没有创建备份的写权限,则不会删除原始输入文件。
在进入循环之前,只需创建一次备份文件:
FILEPATH=*.chordpro
fnbak=$(mktemp) || exit 1
for fn in $FILEPATH; do
echo "$fn"
cmd 'script' "$fn" > "$fnbak" &&
mv -- "$fnbak" "$fn"
done当然,如果使用GNU awk,则根本不需要循环或临时文件,只需:
gawk -i inplace 'script' *.chordpro(将FNR==1{print FILENAME | "cat>&2"}添加到awk脚本中,以查看在处理输入文件名时打印的输入文件名)。
发布于 2020-06-28 14:06:19
这里有一个GNU脚本-它允许内联注释,所以不需要复杂的引用
将其保存在tmp.sh中
#!/bin/bash
# tmp.sh
sed -E '
# strip initial piece
s/\{c: *//
# strip terminal piece
s/ *} *$//
# munge verse with number
s/verse *([0-9]+):? */Verse \1:/i
# munge verse without number
s/verse *$/Verse :/i
# put description on new line
s/: *(.+)$/:\n(\1)/
'用本文档进行测试:
$ ./tmp.sh <<EOF
{c:Verse2}
{c: Verse 2: Bass single}
{c: Verse 2 Rock it}
{c: verse 1}
{c: verse 1}
{c: Verse 1:}
{c:Verse}
EOFVerse 2:
Verse 2:
(Bass single)
Verse 2:
(Rock it)
Verse 1:
Verse 1:
Verse 1:
Verse :很难说为什么您的单个delete命令在未看到整个脚本的情况下意外地运行
您可以尝试sed 4.6中提供的相对较新的--debug选项,或者我发现非常有用的是l和=命令来在多个转换中的任意一点显示行的状态。
我的脚本更像是对脚本进行比较和故障排除以及修改其他测试用例的起点。
希望它能帮上忙
https://stackoverflow.com/questions/62618625
复制相似问题