Perl
был разработан и создан именно для такого рода задач. Его прозвище было «патологический эклектичный мусорный лист».
Прочтите документацию по perlform .Что вы делаете, так это читаете ваши данные (скажем, построчно), анализируете их, вставляете в переменные, а затем вводите команду write
, которая выводит текущие данные на основе формата
, который вы определили.
Для ваших данных у вас может быть формат для заголовка:
format STDOUT_TOP =
Virtual_Machine Vdsks size Physical_Disks
----------------- ------------------ --------- ---------------
.
и другой для каждой строки вывода:
format STDOUT =
@<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<< @>>>>>>>>>>> -
$virtualmachine, @vdisk, @vdisk_size
@<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<~~ @>>>>>>>>>~~ -
$#vdisk<0?'':$virtualmachine, shift(@vdisk), shift(@vdisk_size)
@<<<<<<<<<<<<<<<< - ^<<<<<<<<<<<<~~
$#disks<0?'':$virtualmachine, shift(@disks)
.
Я не уверен, как вы получаете свои данные, но предположим, что они находятся в одном файле, разделенном двумя символами новой строки. Каждый хост представляет собой блок строк:
Virtual Machine Test1 status Running.
Assigned Server OVS001.local
Virtual Disk Test_DISK1 (30) size 61GB
Physical Disk HITACHI (110)
Physical Disk HITACHI (113)
Physical Disk HITACHI (111)
Virtual Machine Test status Running.
Assigned Server OVS002.local
Virtual Disk Test_DISK1 (30) size 41GB
Physical Disk HITACHI (110)
Physical Disk HITACHI (113)
Physical Disk HITACHI (111)
Вы устанавливаете свой символ-разделитель ввода следующим образом:
$/="\n\n";
Каждый раз, когда вы читаете, вы получаете целый блок текста, то есть все строки для одного виртуального хоста.
while (<>) {
# process one virtual machine
}
Теперь начинается самое интересное: анализ ввода. Внутри цикла while вы можете сделать следующее:
my @lines=split("\n");
local @disks=(); # initialize
local $virtualmachine="unknown";
local $physicalserver="unknown";
local @vdisk=("unknown");
local @vdisk_size=("unknown");
foreach (@lines) {
$virtualmachine = $1 if /^Virtual Machine\s+(\S+)\s+status\s+/;
$physicalserver = $1 if /^Assigned Server\s+(\S+)/;
do { push @vdisk,$1; push @vdisk_size,$2; }
if /^Virtual Disk\s+(\S+).* size\s+(\d+\w+)/;
push @disks,$1 if /^Physical Disk\s+(.*)/;
}
write;
Анализ грубый, но обычно эффективный.
find /path/to/base -type l | awk -F/ 'BEGIN {maxlength = 0; longest = "" } length( $NF ) > maxlength { maxlength = length( $NF ); longest = $NF } END { print "longest was", longest, "at", maxlength, "characters." }'
Чтобы сделать awk
более читаемым:
BEGIN {
maxlength = 0
longest = ""
}
length( $NF ) > maxlength {
maxlength = length( $NF )
longest = $NF
}
END {
print "longest was", longest, "at", maxlength, "characters."
}
awk
прекрасно справляется с данными с разделителями. Поскольку пути ограничены /
s, мы используем это как разделитель полей (с переключателем -F
), отслеживаем самое длинное имя, которое мы видели, с помощью переменной longest
и его длину в maxlength
переменная. Некоторая забота и подпитка, чтобы сделать вывод разумным, если ссылки не будут найдены, я оставлю читателю в качестве упражнения.
Сzsh
:
zmodload zsh/stat
by_link_depth() {
zstat -A REPLY +link -- ${1-$REPLY}
REPLY=${REPLY//[^\/]}
}
определяет функцию, которая возвращает косые черты в цели символической ссылки, после чего вы можете использовать ее как метод сортировки для ваших глобусов:
ls -ld -- **/*(D@O+by_link_depth[1])
Выведет список символических ссылок (@
), включая скрытые(D
)с самой глубокой целью (O+by_link_depth
, обратную -сортировку по глубине ссылки, и [1]
выберет первую ).
Здесь в/usr/bin
:
$ ls -ld -- **/*(D@O+by_link_depth[1])
lrwxrwxrwx 1 root root 59 Oct 9 03:08 mptopdf ->../share/texlive/texmf-dist/scripts/context/perl/mptopdf.pl
$ ls -lUd -- **/*(D@O+by_link_depth[1,3])
lrwxrwxrwx 1 root root 59 Oct 9 03:08 mptopdf ->../share/texlive/texmf-dist/scripts/context/perl/mptopdf.pl*
lrwxrwxrwx 1 root root 61 Oct 9 03:09 pkfix-helper ->../share/texlive/texmf-dist/scripts/pkfix-helper/pkfix-helper*
lrwxrwxrwx 1 root root 60 Oct 9 03:09 mkjobtexmf ->../share/texlive/texmf-dist/scripts/mkjobtexmf/mkjobtexmf.pl*
Если вас интересует только максимальная цель ссылки глубины -, а не символическая ссылка, которая указывает на нее, вы можете запустить zstat +link
вместо ls -ld
для этой символической ссылки или вместо этого вы можете определить resolve
и by_depth
функция:
resolve() zstat -A REPLY +link -- ${1-$REPLY}
by_depth() REPLY=${REPLY//[^\/]}
и:
printf '%s\n' **/*(D@O+by_depth+resolve[1])
Где +resolve
переводит символическую ссылку в ее цель для расширения глобуса, а O+by_depth
обратная -сортирует по глубине.
Сbash
(хотя приведенный ниже код никоим образом не bash
специфичен для )и утилит GNU (ваш -printf
уже специфичен для GNU -), вы можете получить что-то похожее с:
find. -type l -printf '%l\0%p\0' | gawk -v RS='\0' -v ORS='\0' -F / '
{n = NF; getline; if (n > max) {max = n; file = $0}}
END {if (max) print file}' | xargs -r0 ls -ld
Или только для самой глубокой цели:
find. -type l -printf '%l\0' | gawk -v RS='\0' -F / '
NF > max {max = NF; target = $0}
END {if (max) print target}'