我一直在仔细研究,发现了"rename"one_answers"sed",我不是很精通计算机,但我已经尝试过了。到目前为止,我可以使用sed来找到我想要搜索的内容,但我无法找到如何用我真正想要的内容替换(希望这有意义)。
因此,场景:我有5000个文件,分为三批(2000、2000和1000),生成它们的程序总是从1-x开始,所以time_step_1。。。我需要文件是连续的(所以不是从1开始的批次)
我尝试过:ls time_step_*|sed 's/[0-9](.*)/mv & time_step_1+2001/'
并打印:
time_step_mv 10.txt time_step_0.txt+2001
time_step_mv 11.txt time_step_1.txt+2001
time_step_mv 12.txt time_step_2.txt+2001
time_step_mv 13.txt time_step_3.txt+2001
time_step_mv 14.txt time_step_4.txt+2001
time_step_mv 15.txt time_step_5.txt+2001
time_step_mv 1.txt time_step_.txt+2001
time_step_mv 2.txt time_step_.txt+2001
time_step_mv 3.txt time_step_.txt+2001
time_step_mv 4.txt time_step_.txt+2001
time_step_mv 5.txt time_step_.txt+2001
time_step_mv 6.txt time_step_.txt+2001
time_step_mv 7.txt time_step_.txt+2001
time_step_mv 8.txt time_step_.txt+2001
time_step_mv 9.txt time_step_.txt+2001
但是文件名本身没有改变我已经多次管理过同样的输出。
我想我理解管道和"保存"字符等,但正如我所说,我不太精通计算机,而且我对我读过的各种帖子中的术语感到困惑。
所有的帮助都非常感谢
所以。。。
首先,让我指出Bash wiki中的ParsingLS页面。它强调了信任ls
命令输出的危险。这并不是说你不应该这样做,但只有当你意识到危险时,你才应该这样做。:)
一些基本的东西:
sed
不是一种编程语言,它不知道如何做数学- 正则表达式中匹配的任何内容都需要在输出中进行说明,甚至是表达式开头和结尾的"隐含"内容。这就是为什么将
mv
嵌入到输出字符串中的原因
你说:
ls time_step_* | sed 's/[0-9](.*)/mv & time_step_1+2001/'
这样做的效果是使用类似time_step_12.txt
的文件名,并用替换字符串仅替换12.txt
。尽管sed不会做数学运算,但您真正想在这里使用的regex已经考虑到了整个输入文本。例如,在bash:中
ls time_step_* | sed -r 's/^(.*_)([0-9]+)(.*)/mv & 123/'
结果是一组命令,您可以通过sh(或bash)通过管道传输,方法是将| sh
添加到行的末尾,以便在验证这些命令是否正确后执行这些命令。注意-r
选项,在许多实现中,它告诉sed将regex解释为ERE而不是BRE。如果这对您不起作用(因为您使用的是较旧的unix、SVR4等),请这样说,我们可以将regex转换为BRE。
我要指出的是,这不是解决这个问题的好方法,尤其是因为,正如我所说,sed不做数学。如果你想给文件名的一个组成部分添加一个整数,那么你需要用一些数学运算的方法来处理它。就像bash。
您可以使用sed提取部分数据,然后在一个简单的while
循环中处理它:
for file in time_step_*.txt; do
number=${file%.txt} # strip off the suffix
number=${number#time_step_} # strip off the prefix
if [[ $number -gt 0 ]]; then
mv "$file" "time_step_$[number+2000].txt"
else
echo "ERROR: $file couldn't be processed" >&2
fi
done
这样做的优点是,除了在外壳内执行mv
之外,可以执行所有操作,因此不会启动不必要的外部进程。当然,你的sed管道不会造成太大的问题。如果你想(记住上面的ParsingLS链接),你可以使用sed来减少bash模式匹配,使其可移植到非bash shell。如果没有错误检查,它可能看起来像这样:
ls time_step_*.txt | sed -r 's/^(.*_)([0-9]+)(.*)/2 &/' | while read number file; do
mv "$file" "time_step_$((number+2000)).txt"
done
这是通过将类似time_step_12.txt
的文件名转换为类似12 time_step_12.txt
的字符串来实现的,这样while
就可以将两个单独的单词读取为单独的变量。请注意,如果数字不是纯数字,则将出现故障。
希望这是有教育意义的。:-)
这应该适用于第二批,然后对第三批执行+3000
for f in time_step_*; do
n=${f%.*}; n=${n##*_}; ((n+=2000));
mv "$f" time_step_$n.txt
done