我需要在 bash 中创建一个循环,遍历一个文件,以检查每条记录是否与以下正则表达式匹配,保留匹配的记录,并将所有匹配的记录重定向到 new_file.csv 文件。有一个特殊之处,那就是我希望标题不受影响。也就是说,它必须在新文件中
下面您可以看到数据集的一个示例:
Country,ISO 3166-1 alpha-3 CODE,Population,Continent,Total Cases,Total Deaths,Tot Cases//1M pop,Tot Deaths/1M pop,Death percentage
Afghanistan,AFG,40462186,Asia,177827,7671,4395,190,4.313743132
Albania,ALB,2872296,Europe,273870,3492,95349,1216,1.275057509
Algeria,DZA,45236699,Africa,265691,6874,5873,152,2.587215976
Andorra,AND,77481,Europe,40024,153,516565,1975,0.382270638
就我而言,我尝试运行的代码是这样的,但它甚至没有运行。
#!/bin/bash
while read line; do
if [["$line"=~^[A-Za-z]*,[A-Z]*,[0-9]*,[A-Za-z]*,[0-9]*,[0-9]*,[0-9]*,[0-9]*]]
then
$line >> new_file.csv;
fi
done < dataset.csv
我知道可以使用 grep -E 来检查整个文件并将其重定向到新文件,但我需要使用迭代序列(for 或 while)来完成。有人能帮我检测出问题出在哪里吗?
错误如下:错误
答案1
在继续阅读之前,请阅读为什么使用 shell 循环来处理文本被认为是不好的做法?
但是如果你必须这样做,两个主要问题是
[[
并且]]
保留字并且必须用空格与周围的标记分开,=~
操作符也必须如此$line >> new_file.csv
不执行任何操作;>>
重定向标准输出,但$line
不产生标准输出
你大概也希望read -r
而不是简单的,read
以防您的数据中有任何反斜杠。
所以
#!/bin/bash
while read -r line; do
if [[ $line =~ ^[A-Za-z]*,[A-Z]*,[0-9]*,[A-Za-z]*,[0-9]*,[0-9]*,[0-9]*,[0-9]* ]]
then
printf '%s\n' "$line" >> new_file.csv;
fi
done < dataset.csv
如果要在输出中包含标题行,那么一个简单的方法就是添加循环计数器:
#!/bin/bash
c=0
while read -r line; do
if (( ++c == 1 )) || [[ $line =~ ^[A-Za-z]*,[A-Z]*,[0-9]*,[A-Za-z]*,[0-9]*,[0-9]*,[0-9]*,[0-9]* ]]
then
printf '%s\n' "$line" >> new_file.csv;
fi
done < dataset.csv
将来你可能会发现www.shellcheck.net有助于调试您的脚本。