在安全处理换行时尝试安全处理文件名的脚本时,我遇到了一个困难的测试用例。
给出输入
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兼容。
答案 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