-4

我正在为一个类项目工作,我们在其中获取一个文件,其中包含描述类的行,如下所示

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

并将其变成

CSC1010,计算机和应用程序,3

我用了:

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

输出:

CSC1010-计算机和应用
CSC1310-介绍编程非MAJ
CSC2010-计算机科学
介绍CSC2310-计算机编程
CSC2320的PRIN-网站开发基金
CSC2510基础CSCI SCI
CSCSCIC3010理论基础 - 计算
CSC3210 -CSC3210-计算机
CSC3210 -CSC3210- - 系统级编程
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 Course hours”的每一行。我想在获得该输出后,我可以使用 sed 中的命令从以 CSC 开头的行的末尾删除新行,并用逗号替换它。之后,我将用逗号替换反斜杠。但是,要做到这一点,我认为我需要使用扩展表达式,因此 sed 可能会出局。我正在考虑使用的正则表达式是(^CSC |[0-9]\.000). 那么,我应该在 sed、awk 或 perl 中执行此操作吗?如果你可以请包括你的推理,为什么使用你建议的任何方法会更有效。

4

2 回答 2

2

在 Perl 中:

while (<>) {
  chomp;
  print if s/^CSC\s+/CSC/ and s/\s+-\s+/,/;
  printf ",%.0f\n", $1 if /^([\d.]+)\s+Credit hours/;
}
于 2013-03-03T18:52:31.773 回答
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将是一个正则表达式黑客,所以我会远离sed解决方案。

于 2013-03-03T18:20:13.770 回答