格式化每个来自Grep的字符串

时间:2014-01-28 08:18:05

标签: shell unix file-io

这是作业!

我正在编写一个shell脚本,它本质上会创建一个书籍数据库,该文件包含所有输入的书籍,如

J.K。罗琳:哈利波特:我不知道:200年代 作者(S)1:TITLE1:Publisher1:YEAR1
作者(S)2:标题2:Publisher2:YEAR2



作者(S)(N):标题(N):出版商(N):年(n)的

现在我使用grep搜索在命令行中输入的特定搜索模式,让我们说“哈利波特”,它将输出所有带有字符串“哈利波特”的条目

我有

的工作
grep $2 "bookprint.txt"

然而它打印的内容与输入到文件中的内容相同......作者1:title1:Publisher1:year1

我想格式化字符串,这样它就会打印4行,每行分成2列,所以输出看起来像

作者(S):.. J.K。罗琳
标题:...........哈利波特
出版商:......我不知道 年份:2000 ..........的
(假装句号是空格我无法正确格式化以显示我想要的内容)

这里的任何提示都将非常感激

3 个答案:

答案 0 :(得分:1)

仅使用sed和grep:

grep "$2" "bookprint.txt" | sed 's/^/Author(s)! /; s/:/\nTitle!     /; s/:/\nPublisher! /; s/:/\nYear!      /; s/!/:/g' 

在您的示例上对其进行测试,以显示sed命令的示例输出:

$ echo "J.K. Rowling:Harry Potter:I dont know:2000's" | sed 's/^/Author(s)! /; s/:/\nTitle!     /; s/:/\nPublisher! /; s/:/\nYear!      /; s/!/:/g' 
Author(s): J.K. Rowling
Title:     Harry Potter
Publisher: I dont know
Year:      2000's

工作原理: sed进行五次换人。通常,每个替换工作看起来像`s / old / new /'。这指示sed找到第一次出现的“old”并将其替换为“new”。因此,例如:

$ echo "this is so old" | sed 's/old/new/'
this is so new

我们使用的第一个替代品是:

s/^/Author(s)! /

对于sed,插入符号(^)是一个特殊字符,它与行的开头匹配。因此,这种替代使得“作者!”被放置在该行的开头。

第二个替代命令是

s/:/\nTitle!     /

这会导致第一次出现冒号(“:”)被“\ nTitle!”替换,其中\n被视为换行符。

如果我们刚刚使用了这两个命令,结果将是:

$ echo "J.K. Rowling:Harry Potter:I dont know:2000's" | sed 's/^/Author(s)! /; s/:/\nTitle!     /' 
Author(s)! J.K. Rowling
Title!     Harry Potter:I dont know:2000's

所以,我们仍然需要投放出版商和年份。

查看上面的输出,您将看到,在完成上述两个替换后,第一个冒号出现在发布者名称之前。所以,第三个替代命令是:

s/:/\nPublisher! /

此命令导致第一次出现冒号(“:”)替换为“\ nPublisher!”。年份行的创建方式与替换相同:

s/:/\nYear!      /

只有这四个替换,我们会:

$ echo "J.K. Rowling:Harry Potter:I dont know:2000's" | sed 's/^/Author(s)! /; s/:/\nTitle!     /; s/:/\nPublisher! /; s/:/\nYear!      /' 
Author(s)! J.K. Rowling
Title!     Harry Potter
Publisher! I dont know
Year!      2000's

除了我们有需要冒号的感叹号外,这看起来还不错。所以,我们需要的最后一次替换是:

s/!/:/g

注意最后的“g”。这告诉sed在全球范围内进行这种替换。因此,这个替换告诉sed用冒号替换每个感叹号。这给出了你想要的结果。

答案 1 :(得分:0)

我建议您尝试使用gawk来完成此类任务(尽管可以使用纯bash完成)。使用gawk,您可以这样做:

gawk -v SEARCH="${2}" -F ":" '$0 ~ SEARCH {for (i=1;i<=NF;i++) { print $i }}'
  1. 这会将您的搜索字符串传递给gawk-v SEARCH="${2}
  2. 设置输入文件的字段分隔符(-F ":"
  3. 搜索搜索字符串的每一行($0
  4. 对于每个匹配项,在单独的行中打印该行的每个字段
  5. 没有gawk(和sed):

    IFS=":" read -a array <<< $(grep $2 bookprint.txt)
    for element in "${array[@]}"
    do
        echo "$element"
    done
    

    注意 仅在只有一条匹配记录时才有效。它可以用更多的记录,我们不是来解决你的功课。您应该自己研究并尝试解决方案。并阅读精细手册。并学习。

答案 2 :(得分:0)

除了shell之外,你不需要任何解析和格式化的东西:

grep "$2" bookprint.txt | while IFS=: read -r author title publisher year; do
    echo "Author(S):  $author"
    echo "Title:      $title"
    echo "Publisher:  $publisher"
    echo "Year:       $year"
done

非常在grep命令中引用"$2"非常重要:如果$ 2包含“Harry Potter”,grep会给你一个错误,比如“没有这样的文件:Potter”(假设你没有名为Potter的文件)