Я хочу найти несколько строк в двух файлах. Если одна строка найдена в обоих файлах, то создайте что-нибудь. Если одна строка найдена только в одном файле, создайте другую.
Мои команды следующие:
####This is for the affirmative sentence in both files
if grep -qw "$users" "$file1" && grep -qw "$users" "$file2"; then
####This is for the affirmative sentence in only one file, and negative for the other one
if grep -qw "$users" "$file1" ! grep -qw "$users" "$file2"; then
Это правильный способ опровергнуть и подтвердить заявления? Я использую оболочку KSH.
Заранее спасибо.
text-processing
awk
grep
ksh
Mareyes
источник
источник
Другой вариант:
источник
Примечание:
((n++))
это расширение ksh (также поддерживаетсяzsh
иbash
). Вsh
синтаксисе POSIX , вам нужноn=$((n + 1))
вместо этого.источник
n=$((n++))
никогда не будет изменять значение п потому , чтоn++
это сообщение приращение: она возвращает текущее значение п, то приращение п; затем вы устанавливаете переменную на возвращаемое значение, которое было исходным n.local IFS=$'\n'; matches=( $(grep -lw "$users" "$file1" "$file2") )
, и используйтеcase "${#matches[@]" in
. @glenn: эта идея относится и к вашему ответу, чтобы избежать многократных вызововgrep
. Трубопровод этоgrep -l | wc -l
также будет работать.Если ваши имена файлов не содержат символов новой строки, вы можете избежать нескольких вызовов
grep
, если grep напечатает имена подходящих файлов и посчитает результаты.Количество матчей
"${#matches[@]}"
.Может быть, есть способ использовать
grep --null -lw
здесь, но я не уверен, как проанализировать вывод . У Bashvar=( array elements )
нет способа использовать\0
разделитель вместо\n
. Может быть,mapfile
встроенный Bash может сделать это? Но, вероятно, нет, потому что вы указываете разделитель с-d string
.Вы могли бы
count=$(grep -l | wc -l)
, но тогда у вас есть два внешних процесса, так что вы могли бы просто запуститьgrep
два файла по отдельности. (Разница междуgrep
противwc
накладных расходов запуска мала по сравнению с вилочным + + Exec динамический компоновщик материал , чтобы запустить отдельный процесс вообще).Кроме того, с
wc -l
вами не узнать, какой файл соответствует.С результатами, захваченными в массиве, это, возможно, уже то, что вы хотите, или если есть ровно 1 совпадение, вы можете проверить, был ли это первый ввод или нет.
$matches
является сокращением для${matches[0]}
первого элемента массива.источник
-z
, нет-0
, упс. Да, это заставит grep распечатать имена файлов, разделенные так,\0
как я уже упоминал в ответе, но как вы можете получить bash для этого? Вы не можете устанавливатьIFS=$'\0'
или вообще делать что-либо еще сfind -print0
выводом стиля напрямую с помощью bash.grep
в любом случае есть несколько вариантов, с которыми приходится иметь дело.mapfile -d $'\0'
вроде работает, но заменяет символы новой строки пробелами (я не пробовал настраиватьIFS
).