Bash 在每行的第n个字段中搜索字符串,然后在每行的末尾追加一个值

Bash 在每行的第n个字段中搜索字符串,然后在每行的末尾追加一个值,bash,shell,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,

我正在创建一个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,则添加第六个字段和“2nd”,如果为true,则添加第六个字段和值“4th”

然后我打算使用第3和第5个字段中的值执行减法。如果第6个字段中的字符串为“第4”,则从第5个字段中减去第3个字段。如果第6个字段中的字符串为“2”,则从第3个字段中减去第5个字段。计算结果需要是每行中的第7个字段

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

编辑:我到目前为止的进展-我认为单独评估和附加每一行是低效的

    while read line; do 
         echo "$(cut -f2 -d ",")"
    done < input.txt
读行时
;做
回显“$(切割-f2-d“,”)
完成

打印每行的第二个字段,但我在计算字符串和在循环中追加行时遇到了困难。对于减法部分,我的计划是使用echo和pipe值到bc,但目前我仍停留在第一步。

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

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

我认为
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
编辑、解释: 当您更改
/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中执行,并且变量在执行后丢失)。

上述构造在纽约重复作为第四个字段。

欢迎使用SO。Stack Overflow是一个面向专业和热心程序员的问答网站。目标是在你的问题中添加一些你自己的代码,至少显示你自己为解决这个问题所做的研究工作。这对awk来说似乎是一件容易的工作。使用
逗号作为字段分隔符,然后编写列比较
如果($2=“New York”){$6=“2nd”},否则{$6=“4th”}
看起来简单易行。@KamilCuk确实是awk最简单的
awk-F“,”{if($2==“newyork”){$6=“2nd”}else{$6=“4th”}print$1“,“$2”,“$3”,“$4”,“$5”,“$6”,“}”input.txt在第一部分为我工作。关于减法部分,是否可以在if语句中设置多个变量?我尝试了
awk-F“,“{if($2==”newyork“){$6=“2nd”&&NYpoints=$3&&OtherPoints=$5}其他{$6=“4th”&&NYpoints=$5&&OtherPoints=$3}打印$1”、“$2”、“$3”、“$4”、“$5”、“$6”、“($NYpoints-$OtherPoints)}”input.txt,但这会将第6个字段更改为整数。如果您确实想使用循环(不应该),当IFS=时使用
,读取-r f1 f2 f4 f5;做完成
。谢谢,我最终使用了这个方法。我想你应该练习使用条件语句或类似的语句。c: