Более эффективный способ поиска отсутствующего номера

С GNU или BSD sed :

sed -s 'x;$!d' -- files... >outfile

...например:

for   i in        10 50 100 1000
do    seq "$i"   >file"$i"
done
sed -s 'x;$!d' -- file[15]0*

9
99
999
49

Вы также можете сделать это с помощью tail :

tail -n2 file[15]0* | sed -ne'n;p;n;n'

9
99
999
49

... но вы должны быть уверены , что в каждом infile есть как минимум две строки, потому что в этом случае sed не -s отделяет какие-либо потоки, и одноразовая операция повлияет на остальную часть вывода. Но tail определенно не будет печатать больше , чем последние две строки в каждом файле, и он будет следовать за каждым набором строк с пустой строкой и вести каждый набор с заголовок указанного в спецификации имени файла (что может вызвать проблемы, если в именах файлов есть символы новой строки) .

Это то, что выводит tail :

tail -n2 file[15]0*

==> file10 <==
9
10

==> file100 <==
99
100

==> file1000 <==
999
1000

==> file50 <==
49
50

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

И если подумать, если меньше двух строк в файле, решение sed выведет пустую строку для этого файла. Если вы предпочитаете, чтобы он вообще ничего не писал для этого файла:

sed -s 'x;$!d;1d' -- file[15]0*

... подойдет.


Хвост | Команда sed работает только со встроенными командами busybox , хотя, к сожалению, busybox sed не не обрабатывает отдельные потоки -s вариант. По крайней мере, в моей сборке нет:

busybox sed --help

BusyBox v1.21.1 (2013-07-28 11:02:27 EDT) multi-call binary.

Usage: sed [-inr] [-f FILE]... [-e CMD]... [FILE]...
or: sed [-inr] CMD [FILE]...

Также досадно, toybox sed (который я предпочитаю и который официально включен в системы Android) ложно сообщает, что делает поддерживает параметр в выводе - help , а затем отказывается распознавать его где-либо еще:

toybox sed -s -e 'x;$!d' -- file[15]0*

usage: sed [-inrE] [-e SCRIPT]...|SCRIPT [-f SCRIPT_FILE]... [FILE...]

Stream editor. Apply one or more editing SCRIPTs to each line of input
(from FILE or stdin) producing output (by default to stdout).

-e  add SCRIPT to list
-f  add contents of SCRIPT_FILE to list
-i  Edit each file in place.
-n  No default output. (Use the p command to output matched lines.)
-r  Use extended regular expression syntax.
-E  Alias for -r.
-s  Treat input files separately (implied by -i)

...

sed: Unknown option s

черт возьми.

1
11.05.2018, 00:38
3 ответа

Dado que sabe de antemano qué elementos deben existir, cree una lista y márquelos a medida que los vea.

awk '
    BEGIN {
        for (i = 0; i < 24; i++) missing[0][sprintf("%02d", i)] = 1;
        for (i = 0; i < 12; i++) missing[1][sprintf("%02d", i)] = 1;
    }
    $7 ~ /^\[[0-9]+\]$/ && $8 ~ /^Slot[0-9]+$/ {
        gsub(/[^0-9]/, "", $7);
        sub(/^[^0-9]+/, "", $8);
        delete missing[$7][$8];
    }
    END {
        for (enclosure in missing) {
            for (slot in missing[enclosure]) {
                printf "Missing enclosure %d Slot%s\n", enclosure, slot;
            }
        }
    }
'
1
27.01.2020, 23:18

Sin awk, para cada recinto:

{ printf '[0] Slot%s\n' {00..23} ; grep -Eo '\[0\] Slot..' disks ; } | sort | uniq -u

En lento -mes:

  • printf '[0] Slot%s\n' {00..23}genera la lista de todos los discos posibles
  • grep -Eo '\[0\] Slot..' disksextrae los discos existentes
  • {..} concatena la salida de los dos comandos
  • sort | uniq -uextrae las líneas que aparecen una sola vez

Puede reemplazar los pasos printf y grep por funciones adecuadas, o la parte printf por un grep similar en otro archivo que es la lista esperada de discos.

3
27.01.2020, 23:18
perl -sle '
  my(@e, @AoA) = qw/ 24 12 /;
  $AoA[$1][$2]++ while /\[([01])]\h+(?:(?!\d)\S)+0*(\d+)$/mg;
  for my $enc ( 0.. $#e ) {
     for my $m_slot ( grep { ! defined $AoA[$enc][$_] } 0.. $e[$enc]-1 ) {
         print "in enclosure $enc - Slot$m_slot is missing.";
     }
  }
 ' -- -_="$DISK_INFO";

Explicación:

°  Initialize the array @e which holds the number of slots in the various enclosures. 

° The Disk info variable is passed into the command line as $_ initialized to $DISK_INFO. 

°  progressively scan and match the $_ variable using the while loop and look for the numbers in the '[..]' and the 'Slot...'  locations. Using these we update the array of array @AoA, it can be viewed as a matrix. 

°  Now once we have ingested all the data, its time to process it now in two for loops. 

° The outer for loops on the enclosures, in our case, they are two. 

° The inner for loop computes the indices of the current enclosure elements that are undefined, IOW, those slots that were never encountered during the data collection drive in the while loop. 
0
27.01.2020, 23:18

Теги

Похожие вопросы