删除分隔的多行字符串的后缀

时间:2016-09-27 17:24:02

标签: bash shell sed posix sh

在安全处理换行时尝试安全处理文件名的脚本时,我遇到了一个困难的测试用例。

给出输入

a.b.c
.d.staging

此输入表示单个文件名,我想删除.staging后缀。我通常会使用类似于| rev | cut -d. -f2- | rev的东西,但这会失败:

echo -ne "a.b.c\\n.d.staging" | rev | cut -d. -f2- | rev

产量

a.b
.d

除了c后缀之外还丢失了staging组件,Markdown隐藏的最后还有一条新线。

到目前为止,我提出的最佳解决方案是使用sed -e ':a' -e 'N' -e '$!ba' -e 's/\(.*\)\..*/\1/',这似乎有效:

echo -ne "a.b.c\\n.d.staging" | sed -e ':a' -e 'N' -e '$!ba' -e 's/\(.*\)\..*/\1/'

产量

a.b.c
.d

这是正确的输出。

这似乎是一个不太优雅的解决方案,因为它正在处理sed处理新行,sed并不是很好。

有更优雅的解决方案吗?理想情况下,POSIX兼容。

2 个答案:

答案 0 :(得分:4)

如果您在变量中有名称,则换行符不是问题。

$ fname=$'a.b.c\n.d.staging'
$ echo "$fname"
a.b.c
.d.staging
$ echo "${fname%.*}"
a.b.c
.d
$

答案 1 :(得分:2)

使用BASH你可以:

$> s=$'a.b.c\n.d.staging'

$> echo "$s"
a.b.c
.d.staging

$> echo "${s%.staging}"
a.b.c
.d

如果没有BASH支持,您可以使用awk这样的RS

printf "%b" 'a.b.c\n.d.staging' | awk -v RS= '{sub(/\.[^.]+$/, "")} 1'

a.b.c
.d