sed 对同一模式的两次操作

sed 对同一模式的两次操作

我使用以下sed命令来显示具有特定形式的文件的名称:

ls -1 *|sed 's/^\(.*\).png/\1\/\1,/g'

如果我有两个名为BOH_Contour.png和 的文件BOV_Web.png,我得到

BOH_Contour/BOH_Contour,
BOV_Web/BOV_Web,

现在我想删除_该结果第二部分中的所有内容并获得

BOH_Contour/BOHContour,
BOV_Web/BOVWeb,

我怎样才能做到这一点?

答案1

这通常是您使用的地方抓住空间:

ls | sed '
  /\.png$/!d; # discard everything but lines ending in .png
  s///;       # remove that .png
  h;          # store on the hold space
  s/_//g;     # remove underscores
  H;          # append (with a newline) to the hold space
  g;          # retrieve that hold space
  s|\n|/|;    # substitute the newline with a /
  s/$/,/;     # add that extra comma.'

答案2

sed只需在after中添加另一个表达式;,例如:

sed 's/^\(.*\).png/\1\/\1,/g;s,/\(.*\)_,/\1,'

但请记住解析ls命令不是一个好习惯

答案3

可能有帮助:

ls -1 *|sed 's/^\(.*\).png/\1\/\1,/g ; : 1 ; s|_\([^/]*$\)|\1|; t 1'

_或者如果文件名中只有 1

ls -1 *|sed 's/^\(.*\).png/\1\/\1,/g ; s|_||2'

答案4

如果所有名称都包含一个下划线,则只需分别匹配名称的两部分即可。您可能不希望在行中的任何位置进行替换,而只是在文件名的末尾进行替换,因此请丢失修饰符g

ls | sed 's/^\(.*\)_\(.*\)\.png$/\1_\2\/\1\2,/'

顺便说一句,ls -1相当于ls不交互使用时的效果。ls *不等于ls,主要区别在于,如果当前目录包含子目录,则ls列出当前目录中的条目,而ls *列出不是子目录的条目加上所有子目录的内容。鉴于这几乎没有用,您可能是指ls.

如果你想删除所有下划线,无论有多少个,虽然可以使用 sed,但在 awk 中更清晰。

ls | awk 'sub(/\.png$/, "") {$0 = $0 "/" gsub(/_/, "", $0) ","} 1'

或者,您可以使用 shell 循环。

for x in *; do
  case $x in
    *.png) x=${x%.png}; printf '%s/\n' "$x"; printf '%s,\n' "$x" | tr -d _;;
  esac
done

相关内容