Как проверить, все ли строки совпадают в файле - PullRequest
0 голосов
/ 07 мая 2018

Я получаю данные от существующей программы, состоящей из строк, разделенных символом канала (|):

$ echo "$list_of_nodes"
NODE-BB-4|NODE-AA-1|DUMMY

Теперь мне нужно проверить, присутствует ли каждый из них в отдельном файле:

$ cat file
NODE-BB-4 1.1.1.1
NODE-AA-1 2.2.2.2
  • случай-1

    должно пройти, когда входная строка равна "NODE-BB-4|NODE-AA-1", поскольку они оба присутствуют в файле,

  • случай-2

    , если входная строка "NODE-BB-4|NODE-AA-1|DUMMY", должна завершиться ошибкой, поскольку "DUMMY" отсутствует в файле.

Вот как я думал об этом, но определенно не самая лучшая идея:

$ echo "$list_of_nodes" |tr '|' '\n' |while read line;
> do grep -q "$line" foo ;
> echo $? ;
> done|awk '{s=s+$0} END{print s}' |awk '$1>0{print "Fail"}'
Fail

Здесь я зацикливаюсь с каждым шаблоном для поиска и сохранения кода возврата, а затем проверяю, больше ли он, чем 0, или нет.

Ответы [ 7 ]

0 голосов
/ 07 мая 2018

Когда узлы указаны в качестве первого столбца в вашем файле, вы можете использовать grep.
Я хочу использовать ваш tr подход, написанный по-другому.

tr '|' '\n' <<< "${list_of_nodes}"

Вы можете сделать вывод похожим на файл с подстановкой процесса

<(tr '|' '\n' <<< "${list_of_nodes}"

Если вы хотите проверить это в первых полях вашего файла, затем обрежьте файл.

cut -d' ' -f1 file

Вы можете использовать выход для другой подстановки процесса и использовать grep (опция x: полное совпадение).

grep -xvf <(cut -d' ' -f1 file) <(tr '|' '\n' <<< "${list_of_nodes}")

Теперь вы можете заменить вывод на sed.

sed -r 's/.+/FAIL: &/'

Части вместе:

grep -xvf <(cut -d' ' -f1 file) <(tr '|' '\n' <<< "${list_of_nodes}") |
   sed 's/.+/FAIL/'
0 голосов
/ 07 мая 2018

еще awk

$ awk 'NR==1 {n=split($0,x,"|"); 
              for(i=1;i<=n;i++) nodes[x[i]]; 
              next} 
 $1 in nodes {delete nodes[$1]} 
         END {for(k in nodes) print "fail: " k}'  <(echo "$list_of_nodes") file

fail: DUMMY

удаляет все видимые узлы и печатает оставшиеся с тегом сбоя.

Или еще один быстрый способ сравнить и вывести отсутствующий узел

$ comm -23 <(tr '|' '\n' <<< "$list_of_nodes" | sort) <(cut -d' ' -f1 file | sort)
DUMMY

Вы можете указать размер выходного файла как неудачный или успешный, но, возможно, также не полезно игнорировать то, что пропущено.

0 голосов
/ 07 мая 2018

Вы можете использовать скрипт bash:

#!/usr/bin/env bash                                                                           

pattern="NODE-BB-4\|NODE-AA-1\|DUMMY"
words=3  # Number of patterns in $pattern
if (($(grep -o "$pattern" inputfile.txt | sort -u | wc -l) < $words)); then                                  
    echo "FAIL: Not all patterns found in input file"                                                                                
else                                                                                          
    echo "SUCCESS: All patterns found in input file"                                                                             
fi

Используются переданные команды:

grep -o "NODE-BB-4\|NODE-AA-1\|DUMMY" inputfile.txt | sort -u | wc -l

, который вернет количество уникальных шаблонов, найденных в inputfile.txt.

0 голосов
/ 07 мая 2018
#!/bin/bash

file="$1"
p="NODE-BB-4|NODE-AA-1|DUMMY"
patterns=${p//|/ }

fileMatchesAllNames () {
  file=$1
  if [[ $# -eq 1 ]]
  then
    echo "$file"
  else
    shift
    pattern=$1
    shift
    grep -q "$pattern" "$file" && fileMatchesAllNames "$file" $@
  fi
}

test -f "$file" && fileMatchesAllNames "$file" $patterns

Функция вызывается с набором шаблонов для поиска, берет первый, если он есть, проверяет его и удаляет с помощью shift для следующего вызова.

grep -q с нетерпением возвращается, как только находит совпадение (подразумевает -m1).

Если файл соответствует всем шаблонам, его имя печатается. В противном случае программа автоматически завершает работу, как только шаблон не может быть сопоставлен.

Он изменен с прежнего решения на вопрос SO, где список файлов должен быть проверен и может быть немного сокращен, поскольку имя файла не нужно передавать функции снова и снова.

#! / Bin / Баш

file="$1"
p="NODE-BB-4|NODE-AA-1|DUMMY"
patterns=${p//|/ }

fileMatchesAllNames () {
  if [[ $# -eq 0 ]]
  then
    echo "$file"
  else
    pattern=$1
    shift
    grep -q "$pattern" "$file" && fileMatchesAllNames $@
  fi
}

test -f "$file" && fileMatchesAllNames $patterns

Обратите внимание, что для работы скрипта в шаблонах не должно быть пробелов.

0 голосов
/ 07 мая 2018

с седом

list_of_nodes='NODE-BB-4|NODE-AA-1|DUMMY'
sed $(echo "$list_of_nodes" | \
sed "s/|/\/!bA;\//g;s/^/ :B;\$bC;N;bB;:C;\//;s/$/\/!bA;d;:A;s\/.*\/fail\/ file/")

Сначала создайте команду sed из list_of_nodes с помощью sed

:B;$bC;N;bB;:C;/NODE-BB-4/!bA;/NODE-AA-1/!bA;/DUMMY/!bA;d;:A;s/.*/fail/ file

И выполнить его

sed $(...)
0 голосов
/ 07 мая 2018

Awk решение:

list_of_nodes="NODE-BB-4|NODE-AA-1|DUMMY"
awk -v nodes_str="$list_of_nodes" \
'BEGIN{ len = split(nodes_str, arr, "|") }{ nodes[$1] }
 END{ for (i=1; i<=len; i++) if (!(arr[i] in nodes)) print "Fail" }' file
0 голосов
/ 07 мая 2018

Вот функция для такой проверки

check() {
   FileToCheck="$1"

   #cycle will check all patterns.
   #if one of patterns will fail, function will stop immediately with Return Code 1
   while read p; do
     grep "${p}" ${FileToCheck} >/dev/null || { echo "${p} not found in ${FileToCheck}"; return 1; }
   done < <( tr '|' '\n' )  #modify input for cycle via tr(replace | by newlines)
   #if we running here, all checks are Okay, Return Code 0.
   return 0
}

Файлы примеров:

$ cat patterns 
NODE-BB-4|NODE-AA-1|DUMMY

$ cat file
NODE-BB-4 1.1.1.1
NODE-AA-1 2.2.2.2

Вот пример использования:

cat patterns | check file
echo $?

Результат:

DUMMY not found in file
1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...