Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex Shell脚本(用于移动文件的正则表达式)_Regex_Shell - Fatal编程技术网

Regex Shell脚本(用于移动文件的正则表达式)

Regex Shell脚本(用于移动文件的正则表达式),regex,shell,Regex,Shell,我有一个文件列表,例如: i60.st082313ea.jpg i61.st51249c5e.jpg i62.stef1fe5f2.jpg 我想通过将起始整数(例如60、61、62)减1来重命名目录中的每个文件 我已经在shell中使用类似以下内容完成了svn重命名: for file in *.xml; do svn mv $file `basename $file xml`json; done; 但当涉及到创建正则表达式,并从文件的一部分中减去1时,我就不知所措了。值得一提的是,该

我有一个文件列表,例如:

i60.st082313ea.jpg
i61.st51249c5e.jpg
i62.stef1fe5f2.jpg

我想通过将起始整数(例如60、61、62)减1来重命名目录中的每个文件

我已经在shell中使用类似以下内容完成了svn重命名:

for file in *.xml;
    do svn mv $file `basename $file xml`json;
done;
但当涉及到创建正则表达式,并从文件的一部分中减去1时,我就不知所措了。值得一提的是,该文件可以在名称的其他位置重复表达式
i[0-9]+
,因此它只需匹配前导字符串

任何帮助/教程/链接都将不胜感激

for file in *.jpg; do
    newfilename=`echo $file | awk -F '.' '{ OFS=".";print "i" substr($1,2,2)+1, $2, $3}'`
    mv $file $newfilename
done;
注意:只有当文件名与您的示例匹配时(例如,整数位于第2和第3位置,并且文件正好有两个
s),此选项才有效


HTH

最棒的是,您的输入非常有规律。所以使用类似正则表达式的

^i([0-9]+)(\..*)$
将从输入的开头开始,匹配“i”作为必需字符,然后匹配十进制数,然后匹配输入的其余部分,直到结束

括号使组可用于捕获匹配项。如果要与bash匹配,则捕获组可在
bash\u REMATCH
(一个数组)中找到。使用这个正则表达式,您有两个捕获组:要递减的数字和文件名的其余部分

要创建新的文件名,您需要将字符“i”、
${BASH_REMATCH[1]}-1和
${BASH_REMATCH[2]}
连接起来

如果与bash不匹配,可以尝试使用
perl
?(另外,您还可以对数字使用
\d
,这是我的最爱。)它在处理器上比
sed
awk
要重一点,但对于您要做的事情来说要容易得多


sed
支持反向引用,但要对其执行算术运算,必须从
sed
表达式(doable)内部调用shell命令
awk
并不真正支持反向引用,但gawk有一个帮助功能,
gensub

无需为每个要重命名的文件创建一个进程,并且在bash shell中(您可以通过键入命令
echo$shell
了解您正在使用哪个shell),假设您的文件名总是以
'i'
开头,后跟一个数字,后跟一个

ls $.jpg | while read file; do
  post_dot=${file#*.}
  pre_dot=${file%%.*}
  number=${pre_dot#i}
  echo "mv "$file" "i$((number-1)).$post_dot""
done

如果对打印结果满意,请删除开头的
'echo'
,以及
mv
行末尾的
'
mv
命令中围绕
$file
i$(number-1)).$post\u dot
对于说明文件名中的空格非常重要。

我编写了一个称为
mv\u re
的小脚本,尽管
mv\u eval
mv\u perl
可能更有意义:

 #!/usr/bin/perl

 foreach (@ARGV) {
    push(@evals,$_);
 }

 sub mv_eval {
     my ($dirname) = @_;
     opendir (my($dh), $dirname) or
         die "Couldn't open dir '$dirname': $!";
     my @fs = readdir $dh;
     foreach $f (@fs) {
         $_ = $f;
         foreach $e (@evals) { eval $e; }
         print "mv '$f' '$_'\n" if ($_ ne $f);
     }
     closedir $dh;
 }

 mv_eval(".");
它将每个参数视为一行perl代码,并直接针对当前目录中的每个文件名运行它们。任何更改的文件名都会打印相应的
mv
命令。因此
mv\u re s/www.//
编写一个脚本,从当前目录中的每个文件中删除第一个
www.


理想情况下,我应该为目录或文件规范添加可选的命令行参数,为
mv
添加替代命令,以及一个选项,这样做而不是为用户编写脚本。

woops。在ubuntu 11.04.im中工作是一个n00b。你是什么意思?你有没有可能包括扩展是.jpg、.jpeg还是.png?如果文件名中有两个连续的空格,则可能无法使用。若要更正此问题,请通过
echo“$file”
更改
echo$file
,或者更好地更改为
printf“%s\n”、“$file”
@jfgagne是的,感谢您指出这一点,当然,它不会使用文件名中的空格。