如何在 sed 或 awk 中搜索一个点和一个数字,并在数字前加上前导零?
How can I search for a dot an a number in sed or awk and prefix the number with a leading zero?
我正在尝试修改大量文件的名称,所有文件都具有以下结构:
4.A.1 Introduction to foo.txt
2.C.3 Lectures on bar.pdf
3.D.6 Processes on baz.mp4
5.A.8 History of foo.txt
我想在最后一位数字前加一个零:
4.A.01 Introduction to foo.txt
2.C.03 Lectures on bar.pdf
3.D.06 Processes on baz.mp4
5.A.08 History of foo.txt
起初我试图通过 sed
(FreeBSD 实现)获取新名称:
ls | sed 's/\.[0-9]/0&/'
但是我在 .
之前得到了零
注意:替换第二个点也可以。我也开放使用 awk
.
这条管道应该适合你:
ls | sed 's/\.\([0-9]\)/.0/'
此处的sed
命令将捕获数字并将其替换为前面的0
。
此处,
引用第一个(并且仅在本例中)捕获组 - 带括号的表达式。
虽然它在这里可能对你有用,但一般来说 slicing and dicing ls
output is fragile, whether using sed
or awk
or anything else. Fortunately one can accomplish this robustly in plain old POSIX sh
using globbing and fancy-pants parameter expansions:
for f in [[:digit:]].[[:alpha:]].[[:digit:]]\ ?*; do
# $f = "[[:digit:]].[[:alpha:]].[[:digit:]] ?*" if no files match.
if [ "$f" != '[[:digit:]].[[:alpha:]].[[:digit:]] ?*' ]; then
tail=${f#*.*.} # filename sans "1.A." prefix
head=${f%"$tail"} # the "1.A." prefix
mv "$f" "${head}0${tail}"
fi
done
(编辑:过滤掉与所需格式不匹配的文件名。)
如果它对其他人有帮助,可以替代@costaparas 回答:
ls | sed -E -e 's/^([0-9][.][A-Z][.])//' > files
然后创建脚本文件:
cat files | awk '{printf "mv \"%s\" \"%s\"\n", [=11=], [=11=]}' | sed 's/\.0/\./' > movefiles.sh
我也开放使用awk
设file.txt
内容为:
4.A.1 Introduction to foo.txt
2.C.3 Lectures on bar.pdf
3.D.6 Processes on baz.mp4
5.A.8 History of foo.txt
然后
awk 'BEGIN{FS=OFS="."}{="0" ;print}' file.txt
产出
4.A.01 Introduction to foo.txt
2.C.03 Lectures on bar.pdf
3.D.06 Processes on baz.mp4
5.A.08 History of foo.txt
说明:我将点 (.
) 设置为字段分隔符和输出字段分隔符,然后对于每一行,我通过连接 0 和所述列将前导 0 添加到第三列 (</code>) .终于我<code>print
这样改线了
(在 GNU Awk 5.0.1 中测试)
这可能对你有用 (GNU sed):
sed 's/^\S*\./&0/' file
这将在每行的第一个非空字符字符串的最后一个 .
之后附加 0
。
我正在尝试修改大量文件的名称,所有文件都具有以下结构:
4.A.1 Introduction to foo.txt
2.C.3 Lectures on bar.pdf
3.D.6 Processes on baz.mp4
5.A.8 History of foo.txt
我想在最后一位数字前加一个零:
4.A.01 Introduction to foo.txt
2.C.03 Lectures on bar.pdf
3.D.06 Processes on baz.mp4
5.A.08 History of foo.txt
起初我试图通过 sed
(FreeBSD 实现)获取新名称:
ls | sed 's/\.[0-9]/0&/'
但是我在 .
注意:替换第二个点也可以。我也开放使用 awk
.
这条管道应该适合你:
ls | sed 's/\.\([0-9]\)/.0/'
此处的sed
命令将捕获数字并将其替换为前面的0
。
此处, 引用第一个(并且仅在本例中)捕获组 - 带括号的表达式。
虽然它在这里可能对你有用,但一般来说 slicing and dicing ls
output is fragile, whether using sed
or awk
or anything else. Fortunately one can accomplish this robustly in plain old POSIX sh
using globbing and fancy-pants parameter expansions:
for f in [[:digit:]].[[:alpha:]].[[:digit:]]\ ?*; do
# $f = "[[:digit:]].[[:alpha:]].[[:digit:]] ?*" if no files match.
if [ "$f" != '[[:digit:]].[[:alpha:]].[[:digit:]] ?*' ]; then
tail=${f#*.*.} # filename sans "1.A." prefix
head=${f%"$tail"} # the "1.A." prefix
mv "$f" "${head}0${tail}"
fi
done
(编辑:过滤掉与所需格式不匹配的文件名。)
如果它对其他人有帮助,可以替代@costaparas 回答:
ls | sed -E -e 's/^([0-9][.][A-Z][.])//' > files
然后创建脚本文件:
cat files | awk '{printf "mv \"%s\" \"%s\"\n", [=11=], [=11=]}' | sed 's/\.0/\./' > movefiles.sh
我也开放使用awk
设file.txt
内容为:
4.A.1 Introduction to foo.txt
2.C.3 Lectures on bar.pdf
3.D.6 Processes on baz.mp4
5.A.8 History of foo.txt
然后
awk 'BEGIN{FS=OFS="."}{="0" ;print}' file.txt
产出
4.A.01 Introduction to foo.txt
2.C.03 Lectures on bar.pdf
3.D.06 Processes on baz.mp4
5.A.08 History of foo.txt
说明:我将点 (.
) 设置为字段分隔符和输出字段分隔符,然后对于每一行,我通过连接 0 和所述列将前导 0 添加到第三列 (</code>) .终于我<code>print
这样改线了
(在 GNU Awk 5.0.1 中测试)
这可能对你有用 (GNU sed):
sed 's/^\S*\./&0/' file
这将在每行的第一个非空字符字符串的最后一个 .
之后附加 0
。