【问题标题】:Pad numerical values in filename with three digit value using sed使用 sed 将文件名中的数值填充为三位数
【发布时间】:2012-03-28 07:14:57
【问题描述】:

我将一个文件名传递给我的 bash 脚本并使用 sed 清理该名称。一些示例文件是:

Test 01.txt
Test v2 01.txt

我想回来:

Test 001.txt
Test v002 001.txt

这是我的脚本

#!/bin/bash

SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
for f in $@
do

j=`basename "$f" ".???"`
BASENAME=`basename "$f" ".???"`
DIRNAME=`dirname "$f"`

j=`echo $j |sed -e 's/\///g'`
j=`echo $j |sed -e 's/_/ /g'`
j=`echo $j |sed -e 's/^\.//'`
j=`echo $j |sed -e 's/\[[^()]*\]//g'`
j=`echo $j |sed -e 's/([^()]*)//g'`
j=`echo $j |sed -e 's/#//g'`
j=`echo $j |sed -e 's/+/\ /g'`
j=`echo $j |sed -e 's/\.\././g'`
j=`echo $j |sed -e 's/\&/and/g'`
j=`echo $j |sed -e 's/\ -/-/g'`
j=`echo $j |sed -e 's/-\ /-/g'`
j=`echo $j |sed -e 's/-{2,}/-/g'`
j=`echo $j |sed -r -e 's/\d+/sprintf("%03d",$&)/e'`
j=`echo $j |sed -e 's/\.\././g'`
j=`echo $j |sed -e "s/\'//g"`
j=`echo $j |sed -r -e 's/ {2,}/ /g'`
j=`echo $j |sed -e 's/\ \././g'`

if [ "$BASENAME" != "$j" ]; then
  mv -v "$f" "$DIRNAME"/"$j"
fi

done

这是问题所在

j=`echo $j |sed -r -e 's/\d+/sprintf("%03d",$&)/e'`

正则表达式可以与 rename 一起使用,但不能与 sed 一起使用。

【问题讨论】:

  • 多行是为了我的理智/调试过程。示例文件名是:Test 01.txt 我想将其重命名为 Test 001.txt。
  • 如果j 最初是basename 的结果,那么这是什么:j=`echo $j |sed -e 's/\///g'`。只有basename / 会输出包含斜线的任何内容。
  • 该行是在使用基本名称之前。只是尚未删除。
  • 我会评论所有这些sed 过滤器。我看到您在转换链的两个不同位置有's/\.\././g'。您将两个连续的点减少为一个,然后再做一次。 - 字符周围的空格可以用s/ *- */-/ 压缩。像s/ {2,}/ / 这样的东西对{m,n} 的使用是无用的。使用s/ */ /s/ \+/ / 可以使用一个或多个空格对一个空格进行两个或多个空格。

标签: bash sed file-rename


【解决方案1】:

代替

sed -r -e 's/\d+/sprintf("%03d",$&)/e'

使用

perl -pe 's/\d+/sprintf("%03d",$&)/ge'

【讨论】:

  • 我通常不赞成用 perl 代替 sed,但我认为这是一个很好的例子。
【解决方案2】:

这可能对你有用(GNU sed):

sed  -r 's/[0-9]+/$(printf "%03d" &)/g;s/.*/echo "&"/e' file
Test 001.txt
Test v002 001.txt

【讨论】:

    【解决方案3】:

    根据您的评论,是的,我了解使用该方法进行调试,这是我的猜测。

    这几乎同样简单,并且不需要稍后进行清理步骤来将结束行和“'”字符上下移动到如下列表中以进行调试(作为替代解决方案)。

    j=$(
      echo "$j" \
      | sed '
        s/\///g
        s/_/ /g
        s/^\.//
        s/\[[^()]*\]//g
        s/([^()]*)//g
        s/#//g
        s/+/\ /g
        s/\.\././g
        s/\&/and/g
        s/\ -/-/g
        s/-\ /-/g
        s/-{2,}/-/g
        s/\.\././g
        s/'"'"'//g
        s/ {2,}/ /g
        s/\ \././g
    ' \
    | awk '/[0-9]/{
       match( $0,/[0-9][0-9]*/ )
       begin=substr($0,1,RSTART); end=substr($0,RSTART+RLENGTH,length($0))
       num=substr($0,RSTART,RSTART+RLENGTH)
       printf("%s%03d%s", begin,num+0, end)
      }'
    )
    

    编辑 转义单引号可能会加倍三倍,即\\'\\\',但我将使用经过验证的真实s/'"'"'//g

    除非您在 Solaris、AIX、HP 或其他旧线 unixen 上使用原始 bourne shell,否则请加入 1990 年代 ;-) 并使用 $( ...) 构造进行命令替换。至少自 1995 年出版的“新 Kornshell 编程语言”以来,反引号已被弃用。

    我希望这会有所帮助。

    【讨论】:

    • 感谢您的信息。我会朝这个方向移动我的脚本。
    猜你喜欢
    • 1970-01-01
    • 2015-11-18
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 2018-07-30
    • 1970-01-01
    • 2011-10-02
    相关资源
    最近更新 更多