在字符串的x,y,z位置插入一个字符

时间:2019-03-10 09:49:51

标签: regex awk sed command-line text-processing

我需要在字符串下面的2个字符之后再在3个字符之后插入“-”减号,例如:

mystring="223334444"

和所需的输出如下: 22-333-4444

我可以按照以下问题插入固定长度的字符,

https://unix.stackexchange.com/questions/5980/how-do-i-insert-a-space-every-four-characters-in-a-long-line

但是在我的情况下,分割不是静态的(不是在第n个位置之后,而是在x,y,z位置之后),我需要一个表达式来使用sed来完成工作。

更新 我可以使用多个sed命令来达到所需的格式: echo 111111111 | sed 's/.\{2\}/&-/' | sed 's/.\{6\}/&-/'

但是我需要知道如何使用一个表达式来实现它

添加更多信息//抱歉,我之前错过了

输出22-333-444将用于某些搜索(使用grep),我可能必须进行数千次此类转换,然后对输出字符串进行搜索,因此此处的处理速度/优化也将是理想的。

根据评论的要求添加有关搜索零件的信息

输入文件示例:

135311046
135310897
135311354
135310944
125312732
125222083
415211804
415222255
415204163
415206020

我正在while循环中通过变量line

逐行读取此文件。

我要做的是将字符串135311046转换为13-531-1046,然后对文件进行grep。

我目前正在使用以下替代 grep $(echo $line | sed 's/.\{2\}/&-/' | sed 's/.\{6\}/&-/') datafile.txt

数据文件包含以下数据:

Line1.P2.ON28.C1.P1.FL1,12-522-2083
Line1.P1.ON19.C1.P1.FL1,12-522-2112
Line1.P1.ON34.C1.P1.FL1,12-530-2766
Line1.P2.ON15.C1.P1.FL1,12-531-1041
Line1.P2.ON15.C1.P3.FL1,12-531-1041
Line1.P2.ON15.C1.P4.FL1,12-531-1041
Line1.P1.ON39.C1.P1.FL1,12-531-1094
Line1.P2.ON26.C1.P1.FL1,12-531-2732
Line1.P1.ON57.C1.P1.FL1,12-533-4019

所以我的主要要求是以一种很好的/紧凑的方式进行转换,并且由于这几千行需要在另一个文件中进行搜索,因此需要快速/优化

3 个答案:

答案 0 :(得分:3)

编辑: :由于OP编辑了具有完整要求的帖子,因此请按此添加解决方案。

awk '
FNR==NR{
  a[substr($0,1,2)"-"substr($0,3,3)"-"substr($0,6)]
  next
}
($NF in a)'   Input_file1  FS=","  Input_file2

它可以在任何awk恕我直言中使用。输出如下。

Line1.P2.ON28.C1.P1.FL1,12-522-2083
Line1.P2.ON26.C1.P1.FL1,12-531-2732


第一个解决方案: :能否请您尝试以下操作。在这里,我将-放在前2个字符之后,然后放在3个字符之后。在这里,我使用sed的功能通过使用\(..\)将值存储到内存中,这意味着让sed知道将第1个2个字符保留在内存中(以后可以通过使用\来访问1)同样,我们可以创建更多的内存占位符,以后可以在替换部分时使用它们的编号来访问它们。

mystring="223334444"
echo "$mystring" | sed 's/\(..\)\(...\)\(....\)/\1-\2-\3/'

第二个解决方案: 或者,如果您想用字符串值替换所有2和所有3(这将不取决于2s和3s的位置,而是直接替换)它们放在字符串的任何地方),然后尝试跟随。

echo "$mystring" | sed -E 's/2+|3+/&-/g'

输出如下。

22-333-4444

答案 1 :(得分:2)

或者,您可以在bash中执行此操作而无需任何正则表达式:

mystring="223334444"
echo "${mystring:0:2}-${mystring:2:3}-${mystring:5}"

22-333-4444

答案 2 :(得分:2)

使用awk:

$ echo $mystring | awk 'BEGIN{FS=OFS=""}{$2=$2 "-";$5=$5 "-"}1'
22-333-4444

解释:

awk 'BEGIN {
    FS=OFS=""   # field separators to null, ie. each char on an individual field
}{
    $2=$2 "-"   # set dashes to all the right places
    $5=$5 "-"
}1'             # output

在GNU awk,mawk,Busybox awk和BWK awk版本20121220上成功进行了测试。

更新我要做的是将字符串135311046转换为13-531-1046,然后对文件进行grep 。一站式awk程序:

$ awk '
BEGIN {
    OFS=""
}
NR==FNR {
    $2=$2 "-";$5=$5 "-"
    a[$0]
    next
}
$NF in a' FS="" input FS="," data

输出:

Line1.P2.ON28.C1.P1.FL1,12-522-2083
Line1.P2.ON26.C1.P1.FL1,12-531-2732

在GNU awk,mawk和Busybox awk上成功测试。在BWK awk版本20121220上失败。