我正在尝试使用sed从文件中删除最后一次出现的}。到目前为止,我有这个:
sed -i 's/\(.*\)}/\1/' file
但这会删除与文件末尾一样多的}。所以如果我的文件看起来像这样:
foo
bar
}
}
}
该命令将删除所有3个}字符。我怎样才能将其限制在最后一次出现?
答案 0 :(得分:7)
有人把我作为解决方案来游戏
sed -i '1h;1!H;$!d;g;s/\(.*\)}/\1/' file
我不确定它和上面的awk解决方案一样好。
答案 1 :(得分:3)
sed是单行简单替换的绝佳工具。对于其他任何事情,只需使用awk,例如使用GNU awk for gensub()和multi-char RS:
$ cat file1
foo
bar
}
}
}
$
$ cat file2
foo
bar
}}}
$
gawk -v RS='^$' -v ORS= '{$0=gensub(/\n?}([^}]*)$/,"\\1","")}1' file1
foo
bar
}
}
$
$ gawk -v RS='^$' -v ORS= '{$0=gensub(/\n?}([^}]*)$/,"\\1","")}1' file2
foo
bar
}}
$
请注意,以上内容将删除最后一个} char和前一个换行符(如果存在),因为我认为这可能是您真正想要的但是如果您只想删除}
并留下尾随在这些情况下换行(因为我认为所有当前发布的sed
解决方案都会这样做),然后从匹配的RE中删除\n?
:
$ gawk -v RS='^$' -v ORS= '{$0=gensub(/}([^}]*)$/,"\\1","")}1' file1
foo
bar
}
}
$
如果您想在不手动指定tmp文件的情况下更改原始文件,只需使用-i inplace
参数:
$ gawk -i inplace -v RS='^$' -v ORS= '{$0=gensub(/}([^}]*)$/,"\\1","")}1' file1
$ cat file1
foo
bar
}
}
$
答案 2 :(得分:0)
使用缓冲区,您可以直接修改文件:
awk 'BEGIN{file=ARGV[1]}{a[NR]=$0}/}/{skip=NR}END{for(i=1;i<=NR;++i)if(i!=skip)print a[i]>file}' file
答案 3 :(得分:0)
向@jthill索取1行文件问题的备注
sed ':a
$ !{N
ba
}
$ s/}\([^}]*\)$/\1/' YourFile
首先需要在缓冲区中加载文件。如果}
单独在一行
答案 4 :(得分:0)
当我读到“用最后 ...做某事”时,我认为“反转文件,先用做一些 ...,重新反向文件“
tac file | awk '!seen && /}/ {$0 = gensub(/(.*)}/, "\\\1", 1); seen = 1} 1' | tac