如何使用awk或sed将数字值替换为“[1.0 - 4.0]”之类的字符串?

时间:2017-01-17 01:30:27

标签: bash awk sed

我有一个CSV文件,我通过一组awk / sed命令进行管道传输。

CSV文件中的某些行如下所示:

10368,"Verizon DSL",DSL,NY,NORTHEAST,-5,-4,"[1.1 - 3.0]","[0.384 - 0.768]"      

其中第8和第9列是表示数值范围的字符串。

如何使用awksed将这些字段替换为数值?范围的开头或范围的结束?

所以这一行最终会成为

10368,"Verizon DSL",DSL,NY,NORTHEAST,-5,-4,1.1,0.384      

10368,"Verizon DSL",DSL,NY,NORTHEAST,-5,-4,3.0,0.768

我到removing the brackets,但过去我被卡住了。我考虑拆分“ - ”,但是我文件中的许多行在最后两列中都有一个常规数值,而不是一个范围,这会使事情变得混乱(我不想最终得到一些具有不同数量的列。)

2 个答案:

答案 0 :(得分:2)

这是一个sed命令,它将获取每个范围并将其分解为两个字段。它会查找"[A - B]"之类的字符串,并将其转换为A,B。如果需要,可以通过更改\1,\2部分轻松修改为仅使用其中一个值。正则表达式假定所有数字在所需小数位的任一侧至少有一位数。因此,1.53.无效。如果您需要,可以使正则表达式更加适应。

$ cat file
10368,"Verizon DSL",DSL,NY,NORTHEAST,-5,-4,"[1.1 - 3.0]","[0.384 - 0.768]"
$ sed -Ee 's|"\[([0-9]+\.[0-9]+) - ([0-9]+\.[0-9]+)\]"|\1,\2|g' file
10368,"Verizon DSL",DSL,NY,NORTHEAST,-5,-4,1.1,3.0,0.384,0.768

答案 1 :(得分:1)

由于您的数据基于 field ,因此awk是合理的选择。

请注意,虽然awk通常不了解双引号字段,但这不是问题,因为双引号字段没有嵌入式 ,个实例。

#!/usr/bin/env bash

useStart1=1  # set to `0` to use the *end* of the *penultimate* fields' range instead.
useStart2=1  # set to `0` to use the *end* of the *last* field's range instead.
awk -v useStart1=$useStart1 -v useStart2=$useStart2 '
  BEGIN { FS=OFS="," }
  { 
        split($(NF-1), tokens1, /[][" -]+/)
        split($NF,     tokens2, /[][" -]+/)
        $(NF-1) = useStart1 ? tokens1[2] : tokens1[3]
        $NF =     useStart2 ? tokens2[2] : tokens2[3]
        print
  }
' <<'EOF'
10368,"Verizon DSL",DSL,NY,NORTHEAST,-5,-4,"[1.1 - 3.0]","[0.384 - 0.768]"
EOF

上面的代码产生:

10368,"Verizon DSL",DSL,NY,NORTHEAST,-5,-4,1.1,0.384

修改$useStart1$useStart2的值会产生适当的变化。