在shell中执行此字符串转换的最佳方法是什么?

时间:2019-01-07 17:07:24

标签: string bash shell awk sh

我正在尝试编写一个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] }

但是为这一操作部署红宝石似乎是过大了。而且我还是想提高我的shell技能,所以想知道是否有人建议在shell中使用更优雅的方式?

感谢您的帮助

6 个答案:

答案 0 :(得分:6)

可以使用bash parameter expansions完成

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

这些都是bash Shell内置结构,因此不需要诸如cutsedtr之类的外部进程。

答案 1 :(得分:1)

您可以尝试执行以下操作:cut -d/ -f3- | cut -d. -f1 | tr / -

说明:

  • cut -d/ -f3--在'/'上分割,并保留第三个字段及其后的所有内容(baz/qux.txt
  • cut -d. -f1-在'。'上分割,保留第一个值(删除文件扩展名)(baz/qux
  • tr / --将所有剩余的“ /”转换为“-”。 (baz-qux

答案 2 :(得分:1)

您可以用一个sed命令完成所有操作

sed -E 's|([^/]*/){,2}||; s|/|-|g; s|\.txt$||' file

\.txt$替换为\.[^.]$,以删除所有扩展名,而不是仅删除.txt

答案 3 :(得分:1)

尝试Perl

$ cat mark_smith.txt
foo/bar/baz/qux.txt
bar/baz/quz.txt
baz/quz/foo.txt

$ perl -F"/" -lane ' @a=@F[2..$#F]; @b=map{s/.txt//g;$_} @a; print join("-",@b) ' mark_smith.txt
baz-qux
quz
foo

$

答案 4 :(得分:1)

假设.仅在文件名中

$ awk -F[/.] '{n=NF; p=$(n-1)} n>4{p=$(n-2)"-"p} {print p}' file

baz-qux
quz
foo

答案 5 :(得分:1)

awk '{gsub(/^.{8}|.txt$/,"")sub(/\//,"-")}1' file

baz-qux
quz
foo