Bash 在每行的第n个字段中搜索字符串,然后在每行的末尾追加一个值
我正在创建一个shell脚本来分析输入文件并将结果发送到输出文件。以下是输入文件中的示例: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,
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: