【问题标题】:String difference in BashBash中的字符串差异
【发布时间】:2010-10-02 01:13:06
【问题描述】:

我正在尝试找到一种方法来确定脚本中两个字符串之间的差异。我可以使用 diff 或 comm 轻松做到这一点,但我不处理文件,我不想将它们输出到文件,进行比较并读回。

我看到 comm、diff、cmp 都允许传递两个文件或一个文件和标准输入 - 我想如果我不想输出两个文件那很好......但它仍然有点糟糕。

一直在思考我可以使用 grep 或正则表达式 - 但我想不会。

【问题讨论】:

  • 你真正想要做什么?
  • 您可以使用子字符串操作和内置测试操作与 IFS 更改进行比较,但您需要知道是否要逐字符、逐字、逐行比较,忽略空格。 ..

标签: string bash


【解决方案1】:

使用diffcom 或任何你想要的:

diff  <(echo "$string1" ) <(echo "$string2")

Greg 的 Bash 常见问题解答:Process Substitution

或使用命名管道

mkfifo ./p
diff - p <<< "$string1" & echo "$string2" > p

Greg 的 Bash 常见问题解答:Working with Named Pipes

命名管道也称为 FIFO。

- 本身用于标准输入。

&lt;&lt;&lt; 是“这里的字符串”。

&amp; 类似于;,但将其置于后台

【讨论】:

  • +1 表示正确答案。 +1 很好地解释了符号。此外,Greg 的 Bash 常见问题解答已移至:mywiki.wooledge.org 以上页面的链接现在位于 mywiki.wooledge.org/ProcessSubstitutionmywiki.wooledge.org/BashFAQ/085
  • 谢谢!而且,这将显示动态文件描述符FUNC(){ echo "$@"; "$@"; }; FUNC diff &lt;(echo a) &lt;(echo b);
  • 我正在寻找用于比较两个 shasum 的那个。不确定是否有更优雅的方式来做到这一点,但它确实有效。
  • 如果 $string1 和 $string2 中有多行,这似乎可以工作,并且 diff 输出添加或减去的行。如果字符串是单行,并且行和两个字符串之间有一些区别呢?
  • @alpha_989,这是你的答案:$ diff &lt;(echo "Here are the letters in String One.") &lt;(echo "Here are the characters in String Two.")\n1c1\n\n&lt; Here are the letters in String One.\n---\n@987654343 ,除了它显示一个进程号,在下一个 $ 之后以 1c1 开头,并等到您按 Enter (或者您可以执行其他命令...)
【解决方案2】:

让我想起了这个问题:How can you diff two pipelines in Bash?

如果你在 bash 会话中,你可以这样做:

diff <cmd1 <cmd2
diff <(foo | bar) <(baz | quux)

使用&lt; 创建匿名命名管道——由 bash 管理——因此它们是自动创建和销毁的,与临时文件不同。

因此,如果您设法将两个不同的字符串隔离为命令的一部分(grep、awk、sed...),您可以执行以下操作 - 例如 - 类似:

diff < grep string1 myFile < grep string2 myFile

(如果你认为你的文件中有string1=very_complicated_valuestring2=another_long_and_complicated_value' 之类的行:在不知道文件的内部格式的情况下,我不能推荐一个精确的命令)

【讨论】:

    【解决方案3】:

    我更喜欢cmp 和 bash 的进程替换功能:

    $ cmp -bl <(echo -n abcda) <(echo -n aqcde)
      2 142 b    161 q
      5 141 a    145 e
    

    在位置 2 上,a b 出现在第一个位置,而 q 出现在第二个位置。在第 5 位,另一个不同之处正在发生。只需用变量替换这些字符串,就完成了。

    【讨论】:

    • 这仅适用于字符串长度相同的情况!
    【解决方案4】:

    假设你有三个字符串

    a="this is a line"
    b="this is"
    c="a line"
    

    从 a 中删除前缀 b

    echo ${a#"$b"}  # a line
    

    从 a 中删除后缀 c

    echo ${a%"$c"}  # this is
    

    【讨论】:

    • 我猜这是 bash 的做法。它工作得很好。不过,这种语法有点难以掌握。
    • @MikaelRoos 同意。更容易阅读(无论如何对我来说)是使用 sed:echo "$a" | sed "s!^$b!!g"(我换掉了标准的 sed 分隔符 / 为 ! 以防要处理的变量是路径。此外,您可以使用 here 字符串而不是 echo: sed ... &lt;&lt;&lt; $a.)
    【解决方案5】:

    另一个例子:

    before="184613 102050 83756 63054"
    after="184613 102050 84192 83756 63054"
    
    comm -23 <(tr ' ' $'\n' <<< $after | sort) <(tr ' ' $'\n' <<< $before | sort)
    

    输出

    84192
    

    Original answer here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-21
      • 1970-01-01
      • 1970-01-01
      • 2022-12-17
      • 1970-01-01
      • 1970-01-01
      • 2012-07-18
      • 1970-01-01
      相关资源
      最近更新 更多