目的是添加前导零,直到逗号之前的所有行都包含九个字符,然后使用 每隔三个数字插入一个字符sed
。
输入
12345,1s4c3v6s3nh6
123456789,9h5vgbdx34dc
12,7h4f45dcvbgh
1234567,09klijnmh563
目前的结果
[vagrant@localhost ~]$ sed -e 's/\([0-9]\{3\}\),/\/\1\//g' file
12/345/1s4c3v6s3nh6
123456/789/9h5vgbdx34dc
12,7h4f45dcvbgh
1234/567/09klijnmh563
预期结果
000/012/345,1s4c3v6s3nh6
123/456/789,9h5vgbdx34dc
000/000/012,7h4f45dcvbgh
001/234/567,09klijnmh563
笔记:
12345
需要成为000012345
并且12
应该导致000000012
。简而言之,重点在于逗号之前的数字顺序。- 行的格式始终是
MAX_9_characters,fixed_12_characters
.即,例如,1234512345,1s4c3v6s3nh6
永远不会驻留在输入文件中。
问题是无法使用 sed 来均衡字符数。这怎么可能实现呢?
答案1
如果您的输入在第二个字段中没有长序列号,请尝试:
$ sed -e 's|^[^,]*|#000000000&|;s|#[^,]*\(.\{9\}\),|\1,|;s|\([0-9]\{3\}\)|\1/|g;s|/\([^0-9]\)|\1|;s|/$||' file
000/012/345,1s4c3v6s3nh6
123/456/789,9h5vgbdx34dc
000/000/012,7h4f45dcvbgh
001/234/567,09klijnmh563
解释
s|^[^,]*|#000000000&|
:我们匹配从开始到第一个的所有内容,
,用制造商和 n 个数字 0 替换它#
,其中 n 是我们要填充的长度。s|#[^,]*\(.\{9\}\),|\1,|
:我们匹配从标记到第一个的所有内容,
,只保留之前的最后 9 个字符,
,丢弃其余的。s|\([0-9]\{3\}\)|\1/|g
:添加/
每 3 个数字序列。s|/\([^0-9]\)|\1|;s|/$||
:如果 after/
不是数字或者/
位于行尾,我们将其删除。
或者更容易使用perl
:
$ perl -F',' -anle '
$F[0] = sprintf "%09s", $F[0];
$F[0] =~ s|.{3}|$&/|g;
chop $F[0];
print join ",",@F;
' file
000/012/345,1s4c3v6s3nh6
123/456/789,9h5vgbdx34dc
000/000/012,7h4f45dcvbgh
001/234/567,09klijnmh563
答案2
这可能可以完成,sed
但它超出了我的 sed-fu 范围。这是一个不同的解决方案:
perl -F, -lane '$F[0]=sprintf("%09s",$F[0]);
$F[0]=~s#(...)(?!$)#$1/#g;
print "$F[0],$F[1]"' file
将-a
每个输入行拆分为字段并将其保存在@F
数组中。设置-F
字段分隔符(,
此处)。删除-l
尾随换行符并在每个调用的末尾添加换行符print
,并n
导致逐行读取输入文件并将 给出的脚本-e
应用于每一行。
该脚本本身做了三件事。首先,它用于向第一个字段sprintf
添加前导( )。然后,它替换第一个字段中所有三个字符的集合(除了最末尾的那些:)/`。最后,它打印现在修改的第一个字段、一个逗号和第二个字段。0
$F[0]
(?!$
) with themselves followed by a
答案3
现在问题已经得到了细化,我们可以将 Gnouc 的sed
答案简化为
sed 's|^|000000000|;s|.*\(...\)\(...\)\(...,\)|\1/\2/\3|' file
或者,如果你想保留一点通用解决方案的味道,
sed 's|^|000000000|;s|.*\(.\{3\}\)\(.\{3\}\)\(.\{3\},\)|\1/\2/\3|' file
这些,至少像其他一些答案一样,假设每一行只有一个逗号。