Pad numerical values in filename with three digit value using sed

北战南征 提交于 2019-12-02 04:10:50

问题


I am passing a filename into my bash script and cleaning the name using sed. A few sample files would be:

Test 01.txt
Test v2 01.txt

I would like to get back:

Test 001.txt
Test v002 001.txt

Here is my script

#!/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

Here is the problem line

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

The regex will work with rename but not with sed.


回答1:


Instead of

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

use

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



回答2:


This might work for you (GNU sed):

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



回答3:


Per your comment, yes I understand about debugging with that method, and that was my guess.

It's almost as easy, and doesn't require a cleanup step later on to move the closing lines and the "'" char up and down a list like below to debug (as an alternative solution).

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)
  }'
)

Edit It may be possible to double-triple up on the escaped single quotes, i.e. \\' or \\\', but I'm going with the tried and true s/'"'"'//g.

Unless you're using the original bourne shell on Solaris, AIX, HP, or other old-line unixen, join the 1990s ;-) and use the $( ...) construct for command substitution. Backquotes have been deprecated since at least 'The New Kornshell programming Language', published 1995.

I hope this helps.



来源:https://stackoverflow.com/questions/9896070/pad-numerical-values-in-filename-with-three-digit-value-using-sed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!