1

我正在编写一个 shell 脚本,它在某些时候必须获取一个文件,在其中搜索一个特定的单词并删除这个单词之后的整个文本(包括单词本身) - 我想 awk 是正确的工具,但我对其中的编程知之甚少。

有人可以帮我吗?

4

6 回答 6

8

我想“awk”是这项工作的一个工具,尽管我认为“sed”对于这个特定的操作来说更简单。规范有点模糊。简单的版本是:

  • 找到包含给定单词的第一行。
  • 删除该行和所有后续行。

为此,我会使用“sed”:

sed '/word/,$d' file

更复杂的版本是:

  • 找到包含给定单词的第一行。
  • 从单词开始删除该行上的文本。
  • 删除所有后续文本行。

我可能仍然使用'sed':

sed -n '1,/word/{s/word.*//;p}' file

这颠倒了逻辑。默认情况下它不打印任何内容,但是对于第 1 行,直到包含单词的第一行它会执行替换(直到包含单词的行之前什么都不做),然后打印。

可以在“awk”中完成吗?并非完全微不足道,因为 'awk' 将输入行自动拆分为单词,并且您必须使用函数来进行替换。

awk '/word/ { if (found == 0) {
                # First line with word
                sub("word.*", "")
                print $0;
                found = 1
              }
            }
            { if (found == 0) print $0; }' file

(已编辑:将 'delete' 更改为 'found',因为 'delete' 是 'awk' 中的保留字。)

在所有这些示例中,输入文件的截断版本被写入标准输出。要就地修改文件,您需要使用 Perl 或 Python 或类似语言,或者将输出捕获到临时文件中,一旦命令完成,您将复制原始文件。(如果您尝试“脚本文件”,您将处理一个空文件。)

有多种早期退出优化可以应用于 sed 和 awk 脚本,例如:

sed '/word/q' file

而且,如果您假设使用 GNU 版本的 awk 或 sed,则有各种非标准扩展可以帮助就地修改文件。

于 2009-06-28T14:53:48.523 回答
1
awk '/word/{exit}1' file
于 2009-07-04T03:27:32.027 回答
1

我假设您的输入是这样的:

Lorem ipsum dolor sit amet,
consectetur adipiscing velit。
Nullam neque sapien,molestie vel congue non,
feugiat quis tellus。Ut quis
nulla mi。Maecenas 舌叶。

并且您希望输出在这样的单词处被切断'vel'

Lorem ipsum dolor sit amet,
consectetur adipiscing velit。
Nullam neque sapien, molestie

在这种情况下,您的 awk 脚本将是:

cat lorem.txt | awk ' 
  /\<vel\>/ 
  {
     print substr($0, 0, match($0, /\<vel\>/) - 1); 
     exit; 
  } 

  { print }
'

您要截断的单词需要替换vel脚本中单词的两个实例。

您也可以安全地将整个脚本放在一行中。

于 2009-06-28T14:54:43.310 回答
0

用 sed 删除部分行,例如:

$ echo '12345 John Smith / red black or blue it is a test' | sed -e 's/\/.*//'

$ 12345 John Smith 
于 2011-06-29T20:00:09.127 回答
0

我不知道如何用 awk 来做,但你可以用 sed 来做:

sed -i~ -e 's/the-word-to-find.*$//' the-file

这将删除从the-word-to-find行尾到包含the-word-to-find. 如果您想在第一次出现 时删除文件的其余部分the-word-to-find,您可以执行以下操作:

sed -i~ -e 's/\(the-word-to-find\).*$/\1/;/the-word-to-find/,$d'
于 2009-06-28T14:57:19.437 回答
0

这个 awk 单行代码应该可以解决问题:{ sub(/ word.*/, ""); print } 对于每一行,如果该行包含以 word 开头(以空格开头)并到达行尾的模式 - 用空字符串替换模式 - 然后打印更新的行。

[ 认为问题可以读取任何一种方式(该行上的整个文本或文件中的整个文本)。如果想跳过文件的其余部分,可以: { skip = gsub(/ word.*/, ""); 打印 ; 如果(跳过)退出}]

于 2009-06-28T15:04:01.060 回答