【问题标题】:Bash compare an input array and a text file and update the fileBash 比较输入数组和文本文件并更新文件
【发布时间】:2016-10-15 21:41:30
【问题描述】:

我已读入一个字符串,根据分隔符将其拆分并将其存储到一个数组中。我想遍历一个文本文件并删除不包含我存储在数组中的字符串的行。假设我的结果数组是['foo', 'bar', 'baz', 'qux', 'quux', 'corge']

我的文本文件是: foo grault bar xyzzy baz quz quux

我想删除行 grault, xyzzy(因为它们不在数组中)并在末尾添加 corge,这样我的结果文件将是: foo bar baz quz quux corge

我打算使用 for 循环遍历我的数组并使用 grep 添加文件中缺少的行,但是我应该如何删除数组中不存在但文件中存在的行?

【问题讨论】:

  • 你从哪里读取字符串?如果它来自文件,您可以让grep 从该文件中读取其模式,而无需自己将其拆分为数组。这对你有用吗?
  • 根据您的描述,无论文件中包含什么内容,您都只是尝试打印数组(我的假设)。您应该添加更多示例或稍微解释一下要求。假设文件不包含任何匹配项,预期的输出是什么?

标签: arrays string bash compare


【解决方案1】:

如果你的原始文件在一个不错的文件中,比如第二个文件,你可以这样做

(grep -f <good list> <bad list>; echo 'corge')

要获得正确的列表,否则您可以尝试

(grep -f <(printf '%s\n' "${array[@]}") <bad file>; echo 'corge')

这将使用进程替换使您的数组像一个文件,grep 可以使用它来为您搜索文件

这将只为您提供原始文件中单词列表中的行,以及您已识别的corge。如果您只是希望其他文件匹配单词列表,尽管您可能会跳过所有行匹配并将您的数组写入文件。

【讨论】:

    【解决方案2】:

    让我们定义批准的单词列表:

    $ words='foo bar baz qux quux corge'
    

    现在,让我们从file 中删除任何不在words 中的单词:

    $ awk -v s="$words" 'BEGIN{split(s,a,/ /); for (i in a) b[a[i]]} ($0 in b){b[$0]++;print}' file
    foo
    bar
    baz
    quux
    

    如果我们要删除任何不在words 中的单词,并在末尾添加words 中不在file 中的任何单词,那么:

    $ awk -v s="$words" 'BEGIN{split(s,a,/ /); for (i in a) b[a[i]]} ($0 in b){b[$0]++;print} END{for (w in b) if (b[w]==0) print w}' file
    foo
    bar
    baz
    quux
    corge
    qux
    

    工作原理

    • -v s="$words"

      这定义了一个 awk 变量 s,它具有 shell 变量 words 的内容。

    • BEGIN{split(s,a,/ /); for (i in a) b[a[i]]}

      在我们读取file 之前,这会将s 中的单词拆分为数组a,其值就是这些单词。然后,我们创建一个关联数组b,每个单词都有一个键。

    • ($0 in b){b[$0]++;print}

      当我们阅读file 时,如果该行与b 中的一个单词匹配,则增加该单词出现次数的计数并打印该单词。

    • END{for (w in b) if (b[w]==0) print w}

      当我们读完文件后,如果数组b中有一个单词没有被打印出来,那就是它的计数b[w]仍然为零,那么就打印出来。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-11
      • 2012-10-23
      • 1970-01-01
      • 1970-01-01
      • 2019-12-21
      • 2019-08-03
      相关资源
      最近更新 更多