sed删除行包含一对()括号

时间:2020-06-28 05:30:53

标签: sed

您好,我创建了一个大型的 sed命令集,用于处理文本文件。 我似乎无法解决的最后一件事是,一行仅由一对()组成

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 :

2 个答案:

答案 0 :(得分:0)

请勿编写冗长的sed脚本,而应使用awk来提高清晰度,效率,鲁棒性,可移植性等。

def alarmClock(self):
        timeString2 = time.strftime("%H:%M:%S")
        getData = self.queryResultTable.get_children()
        

        for data in getData:
            
            for dataValue in self.queryResultTable.item(data)['values']: #sample data: 19:00:00 or 20:00:00
                
                for timeData in timeString2:
                
                    if  timeData == dataValue:
                        print('alarm Raise')

尝试此操作,我认为与您在上面所做的操作相同,但是还修复了代码,以删除 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对,因此我假设您的()可以这样做,而我只是在猜我的awk脚本在“整理”部分中,您实际上想要做什么,因为您没有提供我们可以用来测试的任何示例输入/输出。

顺便说一句,修改输入文件的更常见方法是:

lots of other commands

而不是

fnbak=$(mktemp) || exit 1
cmd 'script' "$fn" > "$fnbak" &&
mv -- "$fnbak" "$fn"

前者只能将备份文件保留足够长的时间来修改原始文件,仅对所有文件使用单个备份,而不是每个文件使用一个备份,并且如果磁盘空间不足,也不会清除原始输入文件或者您没有创建备份的写权限。

进入循环之前,您只需创建一次备份文件即可

fnbak=$fn.bak
mv "$fn" "$fnback"
cmd 'script' "$fnbak" > "$fn"

但是,如果您使用GNU awk,那么您当然根本不需要循环或临时文件,您所需要的只是:

FILEPATH=*.chordpro
fnbak=$(mktemp) || exit 1
for fn in $FILEPATH; do
    echo "$fn"
    cmd 'script' "$fn" > "$fnbak" &&
    mv -- "$fnbak" "$fn"
done

(将gawk -i inplace 'script' *.chordpro 添加到a​​wk脚本中以查看正在处理的输入文件名)。

答案 1 :(得分:0)

这是为您提供的GNU sed脚本-它允许内联注释,因此无需复杂的引用

将其保存在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)/
'

使用heredoc进行测试:

$ ./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}
EOF
Verse 2:
Verse 2:
(Bass single)
Verse 2:
(Rock it)
Verse 1:
Verse 1:
Verse 1:
Verse :

很难说为什么单个删除命令在未看到整个脚本的情况下表现出意外情况

您可以尝试使用sed 4.6中提供的相对较新的--debug选项-或者我发现非常有用的是l=命令来随时显示行的状态进行多次转换

我的脚本更像是您比较脚本并对其进行故障排除并针对其他测试用例进行修改的起点

希望有帮助