2015-06-01 41 views
0

之后,我想是非常复杂的,我用正则表达式很糟糕,所以你们可以帮助。使用SED正则表达式来替换某些字母与数字

看到这个数据源:

User ID:  
a123456 
a12345f 
a1234e6 
d123d56 
b12c456 
c1b3456 
ba23456 

基本上,我想做的事,就是使用正则表达式/ sed的替换字母所有出现为数字以外的第一个字母。字母将始终匹配他们的字母表位置。例如A = 1,B = 2,C = 3等

所以结果集应该是这样的:

User ID: 
    a123456 
    a123456 
    a123456 
    d123456 
    b123456 
    c123456 
    b123456 

有也永远不会是其他任何AJ字母和字符串总是会7个字符长。

任何人都可以点亮一下吗?谢谢! :)

+0

我会'awk'围绕使用空'FS'和在[如何仅使用基本awk打印字符的ASCII值]中完成映射(http://stackoverflow.com/a/14223031/1983854) – fedorqui

+0

您确定在输入中始终有七个字符? –

+0

是 - 始终7.它们是用户标识。它永远不会超过7(包括首字母)。 –

回答

3

这里,你可以使用标准工具cutpastetr做这件事:

$ paste -d'\0' <(cut -c1 file) <(cut -c2- file | tr 'abcdef' '123456') 
a123456 
a123456 
a123456 
d123456 
b123456 
c123456 
b123456 

此连接使用的tr就行了,其余的结果行的第一个字符,使用空字符串。 tr将第一个列表中找到的每个元素替换为第二个列表的相应元素。

0

我看不到复杂性。你的样品看起来像你只是想用数字1-6,以取代7个字符六:

s/^\([a-j0-9]\)[a-j0-9]\{6\}/\1123456/ 

既然放在那里是由位置决定的数字,我们不关心什么,这封信(甚至如果它是一封信)。这里的缺点是我们不保留数字,但他们的样本数据从未改变过。

如果我们想替换字母,我能想到的,是通过使用多重替换的第一种方法:

s/\(.\)a/\11/g 

s/^\([a-j0-9]\{1\}\)[a-j]/\11/ 
s/^\([a-j0-9]\{2\}\)[a-j]/\12/ 
s/^\([a-j0-9]\{3\}\)[a-j]/\13/ 
s/^\([a-j0-9]\{4\}\)[a-j]/\14/ 
s/^\([a-j0-9]\{5\}\)[a-j]/\15/ 
s/^\([a-j0-9]\{6\}\)[a-j]/\16/ 

具体数字,但不包括第一个字母更换字母这种模式将取代两个字符序列,保留第一个,因此每个字母必须运行两次。使用保持空间,我们可以存储第一个字符并使用简单的音译。棘手的部分是加入两个部分,于是sed注入不需要的换行符。

# Store in hold space 
h 
# Remove the first character 
s/^.// 
# Transliterate letters 
y/jabcdefghi// 
# Exchange pattern and hold space 
x 
# Keep the first character 
s/^\(.\).*$/\1/ 
# Print it 
#P 
# Join 
G 
# Remove the newline 
s/^\(.\)./\1/ 

仍在学习的sed的能力:)

+0

我的示例数据可能有点糟糕。用户ID会有所不同。例如a743195,d326578,d918222。这些ID可以表示为d91822b/d9182b2,d918b22,d91h222,d9a8222,dj18222。等。 –

+0

@StevenFalzon是你的样本数据不好。您总是为每个输入集显示完全相同的输出,并且您有1个字母与其余所有字母不同,j,您甚至在您的示例中甚至没有包含该字母。编辑您的问题,以便您的示例帮助显示您的问题。 –

2
sed '/[a-j][0-9a-j]\{6\}$/{h;y/abcdefghij/1234567890/;G;s/.\(.\{6\}\).\(.\).*/\2\1/;}' YourFile 
  • 过滤器上的 “数字” 而已
  • 提醒线(对于第一个字母)
  • 改变所有信数字(包括1号)
  • 添加数字的第一种形式(作为缓冲区中的第二行)
  • 采取第二线路和6最后第一之一的第一信,重新排序和不使用perl保留其他字符
3

为了通过除第一字母相应的数字替换的线a-j字母:

$ perl -pe 'substr($_, 1) =~ tr/a-j/0-9/' input_file 

a=0,而不是a=1,因为j将是10(两位数字)否则。

J = 0,并且不,只使用数字0-9,并且字母只是简单地替换它们的数字副本,所以不会有后者大于j。

为了使j=0a=1

$ perl -pe 'substr($_, 1) =~ tr/ja-i/0-9/' input_file 
+0

它看起来像所需的行为是a = 1,b = 2,...,j = 0,但该方法看起来不错。 –

1
$ awk 'BEGIN{FS=OFS=""} NR>1{for (i=2;i<=NF;i++) if(p=index("jabcdefghi",$i)) $i=p-1} 1' file 
User ID: 
a123456 
a123456 
a123456 
d123456 
b123456 
c123456 
b123456 

注意的是,上述再现标题行User ID:原样。到目前为止,最好的我可以告诉,所有其他发布的解决方案都会将标题行更改为Us5r ID:,因为它们会像在所有后续行上一样进行字母到数字的转换。

+1

我试图搜索如何将每个字母分隔为字段,只是尝试FS,似乎OFS也需要实现这一点。做得好 – NeronLeVelu

+1

将FS设置为空将输入分隔成字符,但是将值赋给任何字段使用OFS的值重新编译记录($ 0),因此将OFS设置为空也是必需的,以便当$ 0被重新编译时, chars。 –