我应该使用sed,awk,perl来改变跨越多行的文本并仅选择所需的信息吗?

时间:2013-03-03 18:07:03

标签: perl sed awk

我正在为一个类的项目工作,我们在这里有一个文件,里面有很多行描述如下所示的类

  

CSC 1010 - 计算机&应用
  计算机和应用。先修课程:高中代数II。计算机的历史,>硬件组件,操作系统,应用软件,数据通信   3.000学分

并将其转换为

  

CSC1010,COMPUTERS&申请,3

我用过:

sed -n 's/^CSC /CSC/p' courses.txt > practice.txt

输出:

  

CSC1010 - 计算机&应用
  CSC1310 - INTRO COMP PROGRAMMING ON-MAJ
  CSC2010 - 计算机科学入门   CSC2310 - 计算机程序设计的原则
  CSC2320 - 网站开发基金
  CSC2510 - COMP SCI的理论基础   CSC3010 - 计算历史
  CSC3210 - 计算机ORG&编程
  CSC3320 - 系统级编程
  CSC3330 - C ++编程
  CSC3410 - 数据结构-CTW
  CSC4110 - 嵌入式系统
  CSC4120 - 机器人介绍

我也用过:

sed '/\.000 Course hours//p' courses.txt > courses10.txt

输出:

  

3   3   3   3   3   3   3   3   3   3   3   4   4   4   4   4   4   4

我的问题是尝试选择sed,awk或perl是否会更好。所以,到目前为止,我已经使用sed来消除那些不是由课程名称或学分小时数组成的行。如上所述。我希望使用正则表达式对文件进行排序,并获得以“CSC”开头或包含“.000课程时间”的每一行。我想在得到输出后我可以在sed中使用一个命令从CSC开始的行末尾删除新行,并用逗号替换它。之后我会用逗号替换反斜杠。但是,要做到这一点,我想我需要使用扩展表达式,所以sed可能会出来。我正在考虑使用的正则表达式是(^CSC |[0-9]\.000)。那么,我应该在sed,awk还是perl中这样做。如果您可以请说明为什么使用您建议的任何方法更有效率的原因。

2 个答案:

答案 0 :(得分:2)

Perl:

while (<>) {
  chomp;
  print if s/^CSC\s+/CSC/ and s/\s+-\s+/,/;
  printf ",%.0f\n", $1 if /^([\d.]+)\s+Credit hours/;
}

答案 1 :(得分:1)

我选择awk,因为您希望匹配并重新格式化行,awk非常适合:

/CSC/ {                 # Lines that match CSC
    split($0,a,"- ")    # Split the line around the hyphen and following space
    gsub(/ /,"",a[1])   # Remove the spaces from the first part of the split
    printf a[1]","a[2]  # Print the line in required format
}
/Credit hours/ {        # Lines that match Credit hours
    printf ",%i\n",$1   # Print the integer value of credit hours  
}

演示:

awk '/CSC/{split($0,a,"- ");gsub(/ /,"",a[1]);printf a[1]","a[2]}/Credit hours/{printf ",%i\n",$1}' file
CSC1010,COMPUTERS & APPLICATIONS,3

我更喜欢awkPerl,这对此没有任何优势(或劣势)。使用sed将是一个regexp hack,因此我远离sed解决方案。