去除前导零但留下单个 0
Stripping the leading zeros but leave a single 0
首先让我说我是 bash 的新手,所以我希望能对您给出的答案进行简单的解释。
我得到了以下代码块:
name="Chapter 0000 (sub s2).cbz "
s=$(echo $name | grep -Eo '[0-9]+([.][0-9]+)?' | tr '\n' ' ' | sed 's/^0*//')
echo $s
readarray -d " " -t myarr <<< "$s"
if [[ $(echo "${myarr[0]} < 100 && ${myarr[0]} >= 10" | bc) -ne 0 ]]; then
myarr[0]="0${myarr[0]}"
elif [[ $(echo "${myarr[0]} < 10" | bc) -ne 0 ]]; then
myarr[0]="00${myarr[0]}"
fi
newName="Chapter ${myarr[0]}.cbz"
echo $newName
哪个(在这种情况下)最终会吐出:
2
(standard_in) 1: syntax error
(standard_in) 1: syntax error
Chapter .cbz
(我相当确定语法错误是因为在进行比较时 ${myarr[0]}
为空)
这不是我想要的输出。我希望代码去除前导 0,但如果全部为 0,则保留一个 0。
所以真正要更改的代码是 sed 's/^0*//')
但我不确定如何更改它。
(预期产出:
in ---> out
1) chapter 8.cbz ---> Chapter 008.cbz
2) chapter 1.3.cbz ---> Chapter 001.3.cbz
3) _23 (sec 2).cbz ---> Chapter 023.cbz
4) chapter 00009.cbz ---> Chapter 009.cbz
5) chap 0000112.5.cbz ---> Chapter 112.5.cbz
6) Chapter 0000 (sub s2).cbz ---> Chapter 000.cbz
到目前为止,我得到的代码适用于 1-3 个,但不适用于前导 0 个案例 (4-6))
这是一个可以解决问题的 awk
脚本:
script.awk
{
str = "000" gensub("(^[[:digit:]]+\.?[[:digit:]]*)( \([^)]+\))?(\.cbz)", "\1", "g", RT);
str = gensub("(^[[:digit:]]+)([[:digit:]]{3})(.*$)", "\2\3", "g", str);
printf("Chapter %s.cbz\n", str);
}
测试输入。1.txt
1) chapter 8.cbz
2) chapter 1.3.cbz
3) _23 (sec 2).cbz
4) chapter 00009.cbz
5) chap 0000112.5.cbz
输出:
awk -f script.awk RS='[[:digit:]]+[\.]?[[:digit:]]*( \([^)]+\))?\.cbz' input.1.txt
Chapter 008.cbz
Chapter 001.3.cbz
Chapter 023.cbz
Chapter 009.cbz
Chapter 112.5.cbz
纯bash:
#!/bin/bash
for name in \
'chapter 8.cbz' \
'chapter 1.3.cbz' \
'_23 (sec 2).cbz' \
'chapter 00009.cbz' \
'chap 0000112.5.cbz' \
'Chapter 0000 (sub s2).cbz' \
'_23.2 (sec 2).cbz'
do
##### The relevant part #####
[[ $name =~ ^[^0-9]*([0-9]+)([0-9.]*)[^.]*(\..*)$ ]]
chapter=$(( 10#${BASH_REMATCH[1]} ))
suffix="${BASH_REMATCH[2]}${BASH_REMATCH[3]}"
newName=$(printf 'Chapter %03d%s' "$chapter" "$suffix")
#############################
echo "$newName"
done
Chapter 008.cbz
Chapter 001.3.cbz
Chapter 023.cbz
Chapter 009.cbz
Chapter 112.5.cbz
Chapter 000.cbz
Chapter 023.2.cbz
备注:
[[ =~ ]]
是在 bash 中使用 ERE 正则表达式的方法。我写的那个有两个捕获组:一个用于捕获第一个出现的数字序列(应该是章节编号),一个用于捕获第一个点(包括在内)之后出现的所有字符。
$(( 10#... ))
将带零前缀的小数转换为普通小数。这是必需的,因为以 0
开头的数字意味着它是八进制而不是十进制。
printf '%03d'
将数字转换为至少 3 位的小数,如果不是,则用零填充左边。
我认为您可以单独通过 sed 实现 table 结果:
sed '
s/^[^0-9]*/000/
s/[^0-9.].*$//
s/\.*$/.cbz/
s/^0*\([0-9]\{3\}\)/Chapter /
' <<'EOD'
chapter 8.cbz
chapter 1.3.cbz
_23 (sec 2).cbz
chapter 00009.cbz
chap 0000112.5.cbz
chap 04567.cbz
EOD
- 第一个命令去除第一个数字之前的所有内容并在前面加上零以确保至少有三位数字。
- 第二个命令删除数字后面的所有内容。 (这可能会留下一个不属于数字的尾随句点,因为代码将数字定义为任何数字和句点序列)。
- 第三个命令删除所有尾随句点并添加所需的后缀。
- 最后的命令删除最长 运行 的前导零,留下(至少)三位数(我添加了一个额外的测试用例来演示)并添加所需的前缀。
运行宁的结果是:
Chapter 008.cbz
Chapter 001.3.cbz
Chapter 023.cbz
Chapter 009.cbz
Chapter 112.5.cbz
Chapter 4567.cbz
使用sed
$ sed 's/[^0-9]*0\+\?\([0-9]\{1,\}\)[^.]*\(\..*\)/Chapter 00/;s/0\+\([0-9]\{3,\}\)//' file
Chapter 008.cbz
Chapter 001.3.cbz
Chapter 023.cbz
Chapter 009.cbz
Chapter 112.5.cbz
s/[^0-9]*0\+\?\([0-9]\{1,\}\)[^.]*\(\..*\)/Chapter 00/
- 去除所有数字直到不为零的数字,然后在开头添加 Chapter
以及去除初始零后的 2 个零。
s/0\+\([0-9]\{3,\}\)//
- 再次去掉多余的零,确保句号前仅保留三位数。
另一个 1 班轮 sed
命令:
正在测试文件输入。1.txt
1) chapter 8.cbz
2) chapter 1.3.cbz
3) _23 (sec 2).cbz
4) chapter 00009.cbz
5) chap 0000112.5.cbz
sed 命令
sed -E '{s/(^[^ ]*)([^[:digit:]]+)([[:digit:]]+[\. ]?[[:digit:]]*)([\. ].*$)/000/;s/([[:digit:]]+)([[:digit:]]{3})(.*$)/Chapter .cbz/}' input.1.txt
输出
Chapter 008.cbz
Chapter 001.3.cbz
Chapter 023.cbz
Chapter 009.cbz
Chapter 112.5.cbz
这可能对你有用 (GNU sed):
sed -E 's/\b0+(0\.)?//' file
删除前导零但保留可选的零。
首先让我说我是 bash 的新手,所以我希望能对您给出的答案进行简单的解释。
我得到了以下代码块:
name="Chapter 0000 (sub s2).cbz "
s=$(echo $name | grep -Eo '[0-9]+([.][0-9]+)?' | tr '\n' ' ' | sed 's/^0*//')
echo $s
readarray -d " " -t myarr <<< "$s"
if [[ $(echo "${myarr[0]} < 100 && ${myarr[0]} >= 10" | bc) -ne 0 ]]; then
myarr[0]="0${myarr[0]}"
elif [[ $(echo "${myarr[0]} < 10" | bc) -ne 0 ]]; then
myarr[0]="00${myarr[0]}"
fi
newName="Chapter ${myarr[0]}.cbz"
echo $newName
哪个(在这种情况下)最终会吐出:
2
(standard_in) 1: syntax error
(standard_in) 1: syntax error
Chapter .cbz
(我相当确定语法错误是因为在进行比较时 ${myarr[0]}
为空)
这不是我想要的输出。我希望代码去除前导 0,但如果全部为 0,则保留一个 0。
所以真正要更改的代码是 sed 's/^0*//')
但我不确定如何更改它。
(预期产出:
in ---> out
1) chapter 8.cbz ---> Chapter 008.cbz
2) chapter 1.3.cbz ---> Chapter 001.3.cbz
3) _23 (sec 2).cbz ---> Chapter 023.cbz
4) chapter 00009.cbz ---> Chapter 009.cbz
5) chap 0000112.5.cbz ---> Chapter 112.5.cbz
6) Chapter 0000 (sub s2).cbz ---> Chapter 000.cbz
到目前为止,我得到的代码适用于 1-3 个,但不适用于前导 0 个案例 (4-6))
这是一个可以解决问题的 awk
脚本:
script.awk
{
str = "000" gensub("(^[[:digit:]]+\.?[[:digit:]]*)( \([^)]+\))?(\.cbz)", "\1", "g", RT);
str = gensub("(^[[:digit:]]+)([[:digit:]]{3})(.*$)", "\2\3", "g", str);
printf("Chapter %s.cbz\n", str);
}
测试输入。1.txt
1) chapter 8.cbz
2) chapter 1.3.cbz
3) _23 (sec 2).cbz
4) chapter 00009.cbz
5) chap 0000112.5.cbz
输出:
awk -f script.awk RS='[[:digit:]]+[\.]?[[:digit:]]*( \([^)]+\))?\.cbz' input.1.txt
Chapter 008.cbz
Chapter 001.3.cbz
Chapter 023.cbz
Chapter 009.cbz
Chapter 112.5.cbz
纯bash:
#!/bin/bash
for name in \
'chapter 8.cbz' \
'chapter 1.3.cbz' \
'_23 (sec 2).cbz' \
'chapter 00009.cbz' \
'chap 0000112.5.cbz' \
'Chapter 0000 (sub s2).cbz' \
'_23.2 (sec 2).cbz'
do
##### The relevant part #####
[[ $name =~ ^[^0-9]*([0-9]+)([0-9.]*)[^.]*(\..*)$ ]]
chapter=$(( 10#${BASH_REMATCH[1]} ))
suffix="${BASH_REMATCH[2]}${BASH_REMATCH[3]}"
newName=$(printf 'Chapter %03d%s' "$chapter" "$suffix")
#############################
echo "$newName"
done
Chapter 008.cbz
Chapter 001.3.cbz
Chapter 023.cbz
Chapter 009.cbz
Chapter 112.5.cbz
Chapter 000.cbz
Chapter 023.2.cbz
备注:
[[ =~ ]]
是在 bash 中使用 ERE 正则表达式的方法。我写的那个有两个捕获组:一个用于捕获第一个出现的数字序列(应该是章节编号),一个用于捕获第一个点(包括在内)之后出现的所有字符。$(( 10#... ))
将带零前缀的小数转换为普通小数。这是必需的,因为以0
开头的数字意味着它是八进制而不是十进制。printf '%03d'
将数字转换为至少 3 位的小数,如果不是,则用零填充左边。
我认为您可以单独通过 sed 实现 table 结果:
sed '
s/^[^0-9]*/000/
s/[^0-9.].*$//
s/\.*$/.cbz/
s/^0*\([0-9]\{3\}\)/Chapter /
' <<'EOD'
chapter 8.cbz
chapter 1.3.cbz
_23 (sec 2).cbz
chapter 00009.cbz
chap 0000112.5.cbz
chap 04567.cbz
EOD
- 第一个命令去除第一个数字之前的所有内容并在前面加上零以确保至少有三位数字。
- 第二个命令删除数字后面的所有内容。 (这可能会留下一个不属于数字的尾随句点,因为代码将数字定义为任何数字和句点序列)。
- 第三个命令删除所有尾随句点并添加所需的后缀。
- 最后的命令删除最长 运行 的前导零,留下(至少)三位数(我添加了一个额外的测试用例来演示)并添加所需的前缀。
运行宁的结果是:
Chapter 008.cbz
Chapter 001.3.cbz
Chapter 023.cbz
Chapter 009.cbz
Chapter 112.5.cbz
Chapter 4567.cbz
使用sed
$ sed 's/[^0-9]*0\+\?\([0-9]\{1,\}\)[^.]*\(\..*\)/Chapter 00/;s/0\+\([0-9]\{3,\}\)//' file
Chapter 008.cbz
Chapter 001.3.cbz
Chapter 023.cbz
Chapter 009.cbz
Chapter 112.5.cbz
s/[^0-9]*0\+\?\([0-9]\{1,\}\)[^.]*\(\..*\)/Chapter 00/
- 去除所有数字直到不为零的数字,然后在开头添加 Chapter
以及去除初始零后的 2 个零。
s/0\+\([0-9]\{3,\}\)//
- 再次去掉多余的零,确保句号前仅保留三位数。
另一个 1 班轮 sed
命令:
正在测试文件输入。1.txt
1) chapter 8.cbz
2) chapter 1.3.cbz
3) _23 (sec 2).cbz
4) chapter 00009.cbz
5) chap 0000112.5.cbz
sed 命令
sed -E '{s/(^[^ ]*)([^[:digit:]]+)([[:digit:]]+[\. ]?[[:digit:]]*)([\. ].*$)/000/;s/([[:digit:]]+)([[:digit:]]{3})(.*$)/Chapter .cbz/}' input.1.txt
输出
Chapter 008.cbz
Chapter 001.3.cbz
Chapter 023.cbz
Chapter 009.cbz
Chapter 112.5.cbz
这可能对你有用 (GNU sed):
sed -E 's/\b0+(0\.)?//' file
删除前导零但保留可选的零。