在每行的第N个字段中搜索字符串,然后将值附加到每行的结尾

时间:2018-11-01 21:32:23

标签: bash shell

我正在创建一个Shell脚本来分析输入文件并将结果发送到输出文件。这是来自输入文件的示例:

01,Rome,30,New York,70,
02,Los Angeles,5,New York,50,
03,New York,40,Tokyo,20,
04,Paris,5,New York,40,
05,New York,20,London,30,
06,Seattle,20,New York,40,
07,Chicago,10,New York,30,
08,New York,20,Miami,40,

这是我在输出文件中需要的结果:

01,Rome,30,New York,70,4th,40,
02,Los Angeles,5,New York,50,4th,45,
03,New York,40,Tokyo,20,2nd,20,
04,Paris,5,New York,40,4th,35,
05,New York,20,London,30,2nd,-10,
06,Seattle,20,New York,40,4th,20,
07,Chicago,10,New York,30,4th,20,
08,New York,20,Miami,40,2nd,-20,

字段之间用逗号分隔。

我打算在每行的第二个字段中搜索字符串“ New York”,如果为true,则将第6个字段添加为“ 2nd”,如果不是,则添加值为“ 4th”的第6个字段

然后,我打算使用第三和第五字段中的值进行减法运算。如果第6个字段中的字符串是“第4个”,请从第5个字段中减去第3个字段。如果第6个字段中的字符串是“ 2nd”,请从第3个字段中减去第5个字段。计算结果必须是每行的第7个字段。

我尝试了awk,sed,grep,echo和bc的组合,但是我觉得我想得太多了。有什么建议吗?

编辑:到目前为止,我的进步-我认为单独评估和附加每行效率不高。

    while read line; do 
         echo "$(cut -f2 -d ",")"
    done < input.txt

打印每行的第二个字段,但是我对评估字符串并将这些行添加到循环中感到困惑。对于减法部分,我的计划是对bc使用echo和pipe值,但此刻我仍停留在第一步。

2 个答案:

答案 0 :(得分:0)

我认为awk是最简单的工作,这里是使用sed的替代方法:

sed -r 's/.*,New York,([0-9]*),.*,([0-9]*),/echo "&2nd,$((\1 - \2))"/e; 
        s/.*,.*,([0-9]*),New York,([0-9]*),/echo "&4th,$((\2 - \1))"/e' input.txt

EDIT,说明: 将/e;更改为/;并删除最后一个e时,您会看到更好的结果。
输入行中以纽约作为第二个字段的部分匹配:

.*,       # First field. It will not eat the whole line, because
          # the rest of the line must match too. 
New York, # Match on the second field
([0-9]*), # The match on the number in parentheses, so it can be used later.
.*,       # next field
([0-9]*), # Second string to remember. I edited the answer, first I had `([0-9]*).`
          # what worked (`.` is a wildcard), but `,` is better.

进行计算时,我们需要外壳。 Shell可以不使用bc之类的东西而进行echo "$((8 - 5))"的计算。 替换字符串将可以执行。

echo "..." # Command to echo the things in quotes
&          # Replace with the complete match, in our case the complete line
2nd,       # Nothing special here.
$((...))   # Perform calculation
\1         # Replace with first remembered match (between parentheses)
\2         # Replace with second remembered match (between parentheses)

sed支持/e执行结果。 (请勿尝试使用/e设置变量,它将在子shell中执行,并且该变量在执行后会丢失。)。
对于纽约作为第四领域重复上述构造。

答案 1 :(得分:-1)

首先替换文件中的空格,因为这样会更容易工作

cat inputfile | sed 's/ /_/g' > tmp && mv tmp inputfile

然后定义一个测试变量:

test=New_York

现在是主要过程:

for i in $(cat inputfile)
do
  if [[ $(echo "$i" | cut -d',' -f2) == "$test" ]]
  then
    int1=$(echo "$i" | cut -d',' -f5)
    int2=$(echo "$i" | cut -d',' -f3)
    result=$(expr "$int2" - "$int1")
    echo $i | sed "s/$/2nd,$result/g" >> outputfile
  else
    int1=$(echo "$i" | cut -d',' -f3)
    int2=$(echo "$i" | cut -d',' -f5)
    result=$(expr "$int2" - "$int1")
    echo $i | sed "s/$/4th,$result/g" >> outputfile
  fi
done

如果要将空格放回文件中:

cat outputfile | sed 's/_/ /g' > tmp && mv tmp outputfile