我的长列表如下:
D6N T69TN K70R M184V T215FEG
结果必须如下:
D006N T069TN K070R M184V T215FEG
我是关于bash的新手,我尝试了基于将其拆分为列并重新格式化的方法。但是,第2和第3个推定列的位置和长度不固定。 谢谢你的帮助!
答案 0 :(得分:2)
您可以使用内置的match
函数使用awk执行此操作:
awk 'match($0, /[0-9]+/) { printf "%s%03d%s\n",
substr($0, 0, RSTART - 1), substr($0, RSTART, RLENGTH), substr($0, RSTART + RLENGTH) }' file
match
成功后,它会设置两个变量RSTART
和RLENGTH
,可用于提取子字符串。中间子字符串使用%03d
格式化,以填充前导零。
不会打印任何与图案不匹配的行。
使用perl的另一个选项:
perl -pe 's/\d{1,3}/sprintf("%03d", $&)/eg' file
这将使用零填充三位数替换任意一到三位数的序列。在此版本中,所有行都会打印出来。
答案 1 :(得分:0)
使用sed
的正则表达式会稍微长一点,但这里有Perl
:
echo "D6N" | perl -pe 's/(\D)(\d)(\D)/${1}0$2$3/g; s/(\D)(\d\d)(\D)/${1}0$2$3/g;'
它会填充由非数字包围的零和2位数字。它通过一个简单的技巧来实现:填充1位数字(一位数字,因此1位数字变为2位数字),然后将2位数字填充为另一个零。
答案 2 :(得分:0)
AFAIK,没有简单的纯Bash解决方案。因此,我更喜欢Perl,因为Perl的表达很简单,Perl无处不在。
s='D6N
T69TN
K70R
M184V
T215FEG'
echo "$s" | perl -ne '/^(\D*)(\d{1,2})(\D*)$/m and printf "%s%03s%s", $1, $2, $3 or print'
答案 3 :(得分:0)
另一个基于sed
的实施:
$ cat testfile
D6N
T69TN
K70R
M184V
T215FEG
$ sed -r 's/[0-9]+/00&/g; s/0?0?([0-9]{3})/\1/g' testfile
D006N
T069TN
K070R
M184V
T215FEG
逻辑:无条件地将2个零前缀加到数字&删除前导零,直到数字长度为3位。
答案 4 :(得分:0)
这个gnu awk也可以完成工作:
src
答案 5 :(得分:0)
使用Bash正则表达式:
#!/bin/bash
re='([[:alpha:]]*)([[:digit:]]*)([[:alpha:]]*)'
while IFS= read -r line; do
[[ $line =~ $re ]]
printf "%s%03d%s\n" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
done < infile
这匹配正则表达式的每一行并捕获三个组:字母,数字,字母。 printf
格式字符串可确保数字组在短于三位数时填充为零。