Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Shell 格式化从Grep提交的每个字符串_Shell_Unix_File Io - Fatal编程技术网

Shell 格式化从Grep提交的每个字符串

Shell 格式化从Grep提交的每个字符串,shell,unix,file-io,Shell,Unix,File Io,这是作业 我正在写一个shell脚本,它将创建一个图书数据库,这个文件保存了所有输入的图书 J.K.罗琳:哈利·波特:我不知道:200秒 作者1:标题1:出版商1:年份1 作者2:标题2:出版商2:年份2 . . . 作者(n):标题(n):出版商(n):年份(n) 现在,我使用grep搜索一个特定的搜索模式,该模式输入到命令行中,比如说“Harry Potter”,它将输出所有带有字符串“Harry Potter in it”的条目 我和他一起工作 grep $2 "bookprint.txt

这是作业

我正在写一个shell脚本,它将创建一个图书数据库,这个文件保存了所有输入的图书

J.K.罗琳:哈利·波特:我不知道:200秒 作者1:标题1:出版商1:年份1
作者2:标题2:出版商2:年份2
.
.
.
作者(n):标题(n):出版商(n):年份(n)

现在,我使用grep搜索一个特定的搜索模式,该模式输入到命令行中,比如说“Harry Potter”,它将输出所有带有字符串“Harry Potter in it”的条目

我和他一起工作

grep $2 "bookprint.txt"
但是,它打印出的所有内容都与输入到文件中的内容相同。。。。作者1:title1:Publisher1:year1

但是,我想格式化字符串,这样它将打印4行单独的行,每行分成2列,因此输出如下

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


非常感谢这里的任何提示

对于此类任务,我建议尝试
gawk
(尽管可以使用纯
bash
)。使用
gawk
你可以像这样做:

gawk -v SEARCH="${2}" -F ":" '$0 ~ SEARCH {for (i=1;i<=NF;i++) { print $i }}'

注意只有在只有一条匹配记录的情况下才有效。有更多的记录是可行的,但我们不是来解决你的家庭作业的。你应该自己研究并尝试解决方案。阅读精美的手册。并学习。

仅使用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查找第一个出现的“旧”并替换为“新”。因此,例如:

$ echo "this is so old" | sed 's/old/new/'
this is so new
我们使用的第一个替代品是:

s/^/Author(s)! /
对于sed,插入符号(
^
)是一个特殊字符,它与行首匹配。因此,此替换将导致“Author(s)!”放在行的开头

第二个替代命令是

s/:/\nTitle!     /
这会导致第一次出现的冒号(“:”)被替换为“\n冒号!”,其中
\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用冒号替换每个感叹号。这将提供您想要的结果。

除了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包含“哈利·波特”,grep会给你一个错误,比如“没有这样的文件:波特”(假设你没有名为波特的文件)

我想我不允许使用该命令,我想我只允许使用find,sed和grepIt可以通过sed完成。我会看看我是否能想出一个答案。哇,谢谢!我对所有的斜杠和东西都不熟悉,你能推荐一个好的指南/网站吗?在那里我可以阅读say“s/^/Author(s)!/;”的确切功能以及它是如何工作的,这样我就可以在将来创建类似的东西了?@coookiemoster我已经添加了一个解释作为开始。有关基础知识的更多信息,请参阅bash简介和sed简介。
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