我有很长的列表如下:庆典0键盘的数字
D6N T69TN K70R M184V T215FEG
的结果必须是这样的:
D006N T069TN K070R M184V T215FEG
我在bash中新,我试图总部设在分裂的方法它在列和重新格式化。然而,第二和第三推定列的位置和长度并不固定。 谢谢你的帮助!
我有很长的列表如下:庆典0键盘的数字
D6N T69TN K70R M184V T215FEG
的结果必须是这样的:
D006N T069TN K070R M184V T215FEG
我在bash中新,我试图总部设在分裂的方法它在列和重新格式化。然而,第二和第三推定列的位置和长度并不固定。 谢谢你的帮助!
为此,您可以用awk,使用内置match
功能:
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
这取代的一至三个数字的任何序列具有零填充三位数。在这个版本中,所有行都被打印出来。
呵呵,我喜欢perl的一个......用'/ e'聪明的工作:-) – anishsane
的确,perl版本工作的很快很顺利!谢谢。 – user3829806
它不再与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;'
将垫被非数字环绕零1年和2位数。它用一个简单的技巧来实现:用一个零填充1位数字(因此1位数字成为2位数字),然后用另一个零填充2位数字。
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'
虽然这个代码可能回答这个问题,但提供 关于_why_和/或_how_的附加上下文会回答 这个问题会显着改善它的长期 值。请[编辑]你的答案,添加一些解释。 –
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个0到号码&移除前导零,直到数为3位长。
这GNU AWK也可以完成这项工作:
awk -v RS='[0-9]+' 'RT{print $0 sprintf("%03d", RT); next} 1' ORS= file
D006N
T069TN
K070R
M184V
T215FEG
使用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
可确保数字组的长度小于三位数字时为零填充。
你如何构建和打印你的“清单”? “列表”从哪里来?也许Bash本身不是正确的工具,但awk或sed可能是? –
同意,bash是一个shell,而不是数据处理器,所以使用像awk,sed,grep等其他工具很可能会变得异常 – edhurtig
@ user3829806你的行总是使用'( [AZ] +)([0-9] +)([AZ] +)',你会一直需要填充最大数字的长度......即数字可能超过3位数? – edhurtig