linux 在所有多行中用新值替换整列

r7xajy2e  于 2023-11-17  发布在  Linux
关注(0)|答案(4)|浏览(148)

我在一个文件中有以下几行

$ cat test.txt
69|1074330570|1,sip:+121345633210x3Bverstat=TN-Validation-Passed|tel:+12134565534|0
69|1077822111|2,;tel:+2223120011~sip:[email protected];|sip:[email protected]|0
69|1077988012|1,sip:+121510016070x3Bverstat=TN-Validation-Passed|tel:+136965339510x3Bnpd|0

字符串
我想替换文件中的第三和第四列只是电话号码如下:

69|1074330570|2134563321|2134565534|0
69|1077822111|2223120011|3123120022|0
69|1077988012|2151001607|3696533951|0


好的一面是所有的文件在第三和第四列都有一个“+”。现在困难的一面是有时我们会在第一行第三列看到11位数字(121345633210)有时候“+”后面没有“1 ",所以如果加号后面有1,就排除1,否则,从“+”号后开始长度。同样,如果有11位数字,只需子串10。此外,如果有多于1个数字,如第2行,我需要选择“+”号后的第一个数字,如2223120011,而不是2223120051。
我尝试了以下方法

awk -F"|"  'BEGIN {FS="+"}{print substr($3,2,10)}' test.txt


但是它为第二行提供了不正确的值,因为它需要在“+”符号之后开始。

ovfsdjhp

ovfsdjhp1#

您可以使用此awk解决方案:

awk '
function extphone(s) {
   sub(/^[^+]*\+1?/, "", s)  # remove all text before + then + and optional 1
   return substr(s, 1, 10)   # extract first 10 characters now
}
BEGIN {FS=OFS="|"}
{
   $3 = extphone($3)
   $4 = extphone($4)
} 1' file

69|1074330570|2134563321|2134565534|0
69|1077822111|2223120011|3123120022|0
69|1077988012|2151001607|3696533951|0

字符串

mf98qq94

mf98qq942#

当前代码的问题:

  • -F"|"FS="+"都定义了输入字段,所以,从技术上讲,你应该选择一个或另一个,而不是两个;在这种情况下,FS="+"优先(即,-F"|"被忽略)
  • 由于总体要求是“替换”第3列和第4列,因此您将希望保留-F"|",但也要将其定义为输出字段x1(推荐:BEGIN { FS=OFS="|"}
  • 然后看看进一步解析第3/第4字段与一些组合的awk字符串函数(例如,split()match()index()substr()

假设/理解:

  • 第三/第四字段始终具有+
  • +后面的字符串始终为10位或11位数字
  • 如果第3/第4个字段有多个+,那么我们只对 * 第一个 * +感兴趣(例如,我们不必根据telsip进一步解析)
  • 似乎我们正在处理北美的电话号码格式(例如,我们不必担心其他国家的不同电话号码格式)

一个awk的想法:

awk '
BEGIN { FS=OFS="|" }
      { for (i=3; i<=4; i++) {                         # loop through 3rd and 4th fields
            split($i,a,"+")                            # split on "+"
            d1 = substr(a[2],1,1)                      # get 1st digit after the "+"
            $i = substr(a[2],(d1==1 ? 2 : 1),10)       # redefine ith field based on value of 1st digit
        }
      }
1                                                      # print current line
' test.txt

字符串

注意:

  • 这种逻辑是基于我们只需要处理北美电话号码格式(10位/11位,国家代码= 1)的假设而硬编码的

这将产生:

69|1074330570|2134563321|2134565534|0
69|1077822111|2223120011|3123120022|0
69|1077988012|2151001607|3696533951|0

h5qlskok

h5qlskok3#

使用GNU awk for gensub()

$ awk '
    BEGIN { FS=OFS="|" }
    {
        for ( i=3; i<=4; i++ ) {
            $i = gensub(/[^+]+\+1?([0-9]{10}).*/,"\\1",1,$i)
        }
        print
    } 
' test.txt
69|1074330570|2134563321|2134565534|0
69|1077822111|2223120011|3123120022|0
69|1077988012|2151001607|3696533951|0

字符串
或使用任何awk:

$ awk '
    BEGIN { FS=OFS="|" }
    {
        for ( i=3; i<=4; i++ ) {
            if ( match($i,/\+1?[0-9]{10}/) ) {
                $i = substr($i,RSTART+RLENGTH-10,10)
            }
        }
        print
    }
' test.txt
69|1074330570|2134563321|2134565534|0
69|1077822111|2223120011|3123120022|0
69|1077988012|2151001607|3696533951|0

nhjlsmyf

nhjlsmyf4#

使用您所展示的示例,请尝试以下GNU awk代码。

awk '
match($0,/^([^|]*\|[^|]*\|)[^+]*\+1*([0-9]+)[^|]*(\|)[^+]*\+1*([0-9]+)[^|]*(\|.*$)/,arr){
  sub(/0$/,"",arr[2])
  sub(/0$/,"",arr[4])
  print arr[1] arr[2] arr[3] arr[4] arr[5]
}
'  Input_file

字符串

  • 解释说明:* 为上述代码增加详细解释说明。
  • 使用GNU awkmatch函数在其中使用正则表达式,它创建捕获组,稍后我们可以使用它们来获取所需的输出。
  • match函数中使用正则表达式^([^|]*\|[^|]*\|)[^+]*\+1*([0-9]+)[^|]*(\|)[^+]*\+1*([0-9]+)[^|]*(\|.*$)
  • 如果找到正则表达式的匹配,则在第二和第四捕获组的最后删除0,在这里使用sub
  • 然后打印所有5个捕获组以获得所需的输出。

相关问题