Заполните числовые значения в имени файла трехзначным значением с помощью sed

Я передаю имя файла в мой скрипт 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'`

Регулярное выражение будет работать с переименованием, но не с sed.

3 ответа

Решение

Вместо

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

использование

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

Это может работать для вас (GNU sed):

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

На ваш комментарий да, я понимаю об отладке с помощью этого метода, и это было мое предположение.

Это почти так же просто, и не требует последующего шага очистки, чтобы переместить закрывающие строки и символ "" "вверх и вниз по списку, как показано ниже, для отладки (в качестве альтернативного решения).

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,

Если вы не используете оригинальную оболочку Bourne в Solaris, AIX, HP или других старых версиях Unixen, присоединяйтесь к 1990-м годам;-) и используйте $( ...) конструкция для подстановки команд. Обратные кавычки устарели, по крайней мере, в "Новом языке программирования Kornshell", опубликованном в 1995 году.

Надеюсь, это поможет.

Другие вопросы по тегам