首页 > 解决方案 > 在 shell 中进行这种字符串转换的最佳方法是什么?

问题描述

我正在尝试编写一个需要转换以下形式的输入的 shell 脚本:

foo/bar/baz/qux.txt
bar/baz/quz.txt
baz/quz/foo.txt

进入:

baz-qux
quz
foo

即拆分'/',删除前2 段,删除'.txt' 并用剩余的斜杠替换连字符。

使用 tr 进行替换似乎很简单:

paths=$(cat <<- EOF
foo/bar/baz/qux.txt
bar/baz/quz.txt
baz/quz/foo.txt
EOF
)

echo $paths | tr '/' '-' | tr '.txt' ' '

我尝试过各种形式的

cut -d '/' -f x

获得必要的部分,但我来不及。

我是一个红宝石人,很想伸手去拿我的锤子,只用红宝石:

lines.each { |s| s.split('/')[2..-1].join('-').split('.')[0] }

但是为这一操作部署 ruby​​ 似乎有点矫枉过正。而且我还是想提高我的 shell 技能,所以想知道是否有更优雅的方式有人会推荐在 shell 中执行此操作?

谢谢你的帮助

标签: stringbashshellawksh

解决方案


可以使用bash 参数扩展来完成:

for name in foo/bar/baz/qux.txt bar/baz/quz.txt baz/quz/foo.txt; do
    new=${name#*/}   # drop the shortest prefix match for */, thus everything up to first /
    new=${new#*/}    # repeat, dropping the second segment
    new=${new%.txt}  # drop shortest suffix match for .txt
    new=${new//\//-} # convert any remaining slashes
    echo "$new"
done

给出:

baz-qux
quz
foo

这些都是bashshell 内置结构,因此不需要像cut,sedtr所需的外部进程。


推荐阅读