使用循环检查数据集中与正则表达式匹配的记录

使用循环检查数据集中与正则表达式匹配的记录

我需要在 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 循环来处理文本被认为是不好的做法?

但是如果你必须这样做,两个主要问题是

  1. [[并且]]保留字并且必须用空格与周围的标记分开,=~操作符也必须如此

  2. $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有助于调试您的脚本。

相关内容