Bash string difference


70

Я пытаюсь найти способ определить разницу между двумя строками в моем скрипте. Я мог бы легко сделать это с помощью diff или comm, но я не имею дело с файлами, и я бы предпочел не выводить их в файлы, сравнивать и читать.

Я вижу, что comm, diff, cmp позволяют пропускать либо два файла ИЛИ файл и стандартный ввод - я думаю, это хорошо, если я не хочу выводить два файла ... но это все еще отстой.

Копаясь вокруг мышления, я могу использовать grep или регулярные выражения, но, я думаю, нет.

Спасибо заранее,

+1

что это вы на самом деле хотите сделать? 18 янв. 092009-01-18 02:51:04

  0

Вы можете использовать манипуляции подстроки и встроенные тестовые операции с изменениями IFS для сравнения, но вам нужно знать, хотите ли вы сравнивать символ по символу, слово за словом, по очереди, игнорировать пробел ... 21 июл. 122012-07-21 10:33:51

  0

См. Https://stackoverflow.com/questions/34376884/highlight-string-differences 10 мар. 182018-03-10 17:20:29

9

Напоминает мне этот вопрос: How can you diff two pipelines in Bash?

Если вы находитесь в Баш сессии, вы могли бы сделать:

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

с < создавая анонимные именованные каналы - - управляются bash - поэтому они создаются и уничтожаются автоматически, в отличие от временных файлов.

Так что, если вам удастся изолировать две разные строки в составе команды (Grep, AWK, Sed, ...), вы можете сделать - например - что-то вроде:

diff < grep string1 myFile < grep string2 myFile 

(если вы думаете, что у вас в файле строки, как string1=very_complicated_value и string2=another_long_and_complicated_value': не зная внутренний формат файла, я не могу рекомендовать точную команду)


124

diff Использование или com или все, что вы хотите:

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

Грег Bash FAQ: Process Substitution

или именованного канал

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

Грег Bash Справка: Working with Named Pipes

Названные трубы также известна как FIFO.

- сам по себе предназначен для стандартного ввода.

<<< - это «настоящая строка».

&, как ;, но ставит его в фоновом режиме

+3

+1 для правильного ответа. +1 для отличного объяснения символов. Кроме того, FAQ Greg's Bash переместился на: http://mywiki.wooledge.org/. Ссылки на приведенные выше страницы теперь находятся на http://mywiki.wooledge.org/ProcessSubstitution и http://mywiki.wooledge.org/ BashFAQ/085 20 фев. 132013-02-20 17:30:24

  0

thx! а также это покажет динамические файловые дескрипторы 'FUNC() {echo" $ @ "; "$ @"; }; FUNC diff <(echo a) <(echo b); ' 16 апр. 152015-04-16 01:30:54

  0

Я искал это для компиляции двух шаусов. Не уверен, есть ли более элегантный способ сделать это, но он работает. 23 авг. 162016-08-23 08:29:09

  0

Кажется, что это работает, если в $ string1 и $ string2 есть несколько строк, а diff выводит строки, которые были добавлены или вычтены. Что, если строка - это одна строка, а строка - и какая-то разница между двумя строками? 10 авг. 172017-08-10 15:28:00


11

Я предпочитаю cmp и процесс Замены особенности Баша:

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

Говоря о позиции 2, абы происходят в первом, но водна для второй. В положении 5 происходит другое различие. Просто замените эти строки на переменные, и все готово.

  0

Это работает только тогда, когда строки имеют одинаковую длину! 06 май. 162016-05-06 11:58:04


8

Скажем, у вас есть три строки

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

Чтобы удалить префикс б из

echo ${a#"$b"} 

Чтобы удалить суффикс C из

echo ${a%"$c"} 
+1

Я предполагаю, что это способ bash сделать это. Он работал красиво. Однако этот синтаксис немного сложно понять. 05 ноя. 142014-11-05 20:39:25

  0

@MikaelRoos Согласен. Легче читать (для меня в любом случае) было бы использовать sed: 'echo '$ a" | sed «s!^$ b !! g» '(я заменил стандартный разделитель sed/for! в случае, если обрабатываемые переменные являются путями. Кроме того, вы можете использовать следующую строку вместо echo:' sed ... <<< $ a'.) 08 сен. 162016-09-08 18:06:40