Есть ли способ определить последнюю запись при просмотре массива? Создание команды поиска из массива

Используя strace , вы можете увидеть, чем занимается консоль .

$ strace -s 2000 -o konsole.log
...
...
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=2655, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f316d8fc000
read(3, "root:x:0:0:root:/root:/bin/bash\nbin:x:1:1:bin:/bin:/sbin/nologin\ndaemon:x:2:2:daemon:/sbin:/sbin/nologin\nadm:x:3:4:adm:/var/adm:/sbin/nologin\nlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\nsync:x:5:0:sync:/sbin:/bin/sy
nc\nshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\nhalt:x:7:0:halt:/sbin:/sbin/halt\nmail:x:8:12:mail:/var/spool/mail:/sbin/nologin\noperator:x:11:0:operator:/root:/sbin/nologin\ngames:x:12:100:games:/usr/games:/sbin/nologin\nf
tp:x:14:50:FTP User:/var/ftp:/sbin/nologin\nnobody:x:99:99:Nobody:/:/sbin/nologin\ndbus:x:81:81:System message bus:/:/sbin/nologin\nsystemd-journal-gateway:x:191:191:Journal Gateway:/var/log/journal:/usr/sbin/nologin\npolkitd:
x:999:999:User for polkitd:/:/sbin/nologin\nusbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin\ncolord:x:998:997:User for colord:/var/lib/colord:/sbin/nologin\nrpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin\nqemu:x:107:
107:qemu user:/:/sbin/nologin\nrtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin\ntss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin\nradvd:x:75:75:radvd user:/:/sbin/nologin\nabr
t:x:173:173::/etc/abrt:/sbin/nologin\nopenvpn:x:997:996:OpenVPN:/etc/openvpn:/sbin/nologin\nunbound:x:996:995:Unbound DNS resolver:/etc/unbound:/sbin/nologin\nsaslauth:x:995:76:\"Saslauthd user\":/run/saslauthd:/sbin/nologin\n
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin\navahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin\nrpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin\nnfsnobody
:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin\nnm-openconnect:x:994:994:NetworkManager user for OpenConnect:/:/sbin/nologin\nmailnull:x:47:47::/var/spool/mqueue:/sbin/nologin\nsmmsp:x:51:51::/var/spool/mqueue:/s
bin/nologin\nsshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin\ntcpdump:x:72:72::/:/sbin/nologin\npulse:x:993:993:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin\ngdm:x:42:42::/var/lib/gdm:/sbin/nologin\
ngnome-initial-"..., 4096) = 2655
close(3)                                = 0
...

Konsole довольно быстро считывает содержимое / etc / passwd , и вы просто не видите его с помощью lsof . Это типичная проблема, когда файл открывается, быстро читается, а затем закрывается.

Должен ли я быть обеспокоен?

Это, кстати, не имеет значения. Мой gnome-terminal делает то же самое. Ход событий может немного сбивать с толку, но Konsole запрашивает у системы некоторую информацию. В этом случае что-то вроде домашнего каталога пользователя.

Итак, система вызывает NSS (файл конфигурации переключателя службы имен):

open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3

В этом файле есть строка, в частности, эта строка:

passwd:     files

Эта строка сообщает NSS, где может быть "база данных" 'passwd' нашел.Эта строка сообщает NSS, что ресурс находится в файлах. Затем система открывает файл / etc / passwd для поиска домашнего каталога пользователя.

ПРИМЕЧАНИЕ. Дальнейшее копание, похоже, вызвано Bash. Выполнение strace только Bash показывает то же самое.

$ strace -s 2000 -o bash.log bash

Дополнительная литература

Если вас действительно интересует, как работает NSS, обратитесь к страницам руководства nsswitch.conf и nss . NSS является модульным и может использовать различные серверные технологии для своих «баз данных».

Например:

       /etc/nsswitch.conf       NSS configuration file.
       /lib/libnss_compat.so.X  implements "compat" source.
       /lib/libnss_db.so.X      implements "db" source.
       /lib/libnss_dns.so.X     implements "dns" source.
       /lib/libnss_files.so.X   implements "files" source.
       /lib/libnss_hesiod.so.X  implements "hesiod" source.
       /lib/libnss_nis.so.X     implements "nis" source.
       /lib/libnss_nisplus.so.X implements "nisplus" source.
2
08.02.2019, 23:10
3 ответа

Добавьте параметры в другом порядке, затем удалите первый элемент:

EXT=(sh mkv txt)

EXT_OPTS=()
# Now build the find command from the array
for i in "${EXT[@]}"; do
    EXT_OPTS+=( -o -iname "*.$i" )
done

# remove the first thing in EXT_OPTS
EXT_OPTS=( "${EXT_OPTS[@]:1}" )

Если вы не используете $@ни для чего, это выглядит более аккуратно:

EXT=(sh mkv txt)

# Empty $@
set --

# Now build the find command from the array
for i in "${EXT[@]}"; do
    set -- -o -iname "*.$i"
done

# remove the first thing in $@
shift

# assign to EXT_OPTS (this would be optional, you could just use "$@" later)
EXTS_OPTS=( "$@" )

Я предпочитаю добавлять -o -iname "*.$i"к промежуточному массиву, потому что "*.$i" -o -inameтрудно читать. Добавление -o -iname "*.$i"к $@также делает действительно простым shiftот первого -oпосле цикла.


В сочетании с несколькими исключениями (имена для игнорирования):

extensions=( sh mkv txt )
ignore_patterns=( '*sample*' '*test*' )

include=()
# Now build the find command from the array
for ext in "${extensions[@]}"; do
    include+=( -o -iname "*.$ext" )
done

# Do the ignore list:
ignore=()
for pattern in "${ignore_patterns[@]}"; do
    ignore=( -o -iname "$pattern" )
done

# combine:
EXT_OPTS=( '(' "${include[@]:1}" ')' ! '(' "${ignore[@]:1}" ')' )

Обратите внимание на круглые скобки, добавленные для сортировки приоритета тестов.

1
27.01.2020, 22:08

Проще всего исправить массив постфактум. После doneдобавление

unset 'EXT_OPTS[-1]'
unset 'EXT_OPTS[-1]'

удалит последние два значения(-oи -iname), а затем вы можете добавить другие, если хотите (, или просто замените их, чтобы они начинались с ).

Может быть еще немного проще просто добавить избыточное условие:

EXT_OPTS+=( "*.${EXT[0]}" )

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

1
27.01.2020, 22:08

Is there a way of determining the last entry when looping through an array?

Просто чтобы ответить на вопрос буквально, я не думаю, что вы можете сделать это напрямую. Но вы, конечно, можете подсчитать элементы во время цикла и сравнить это с размером массива:

test=(foo bar blah qwerty)
count=${#test[@]}
n=1
for x in "${test[@]}"; do
   last=""
   if [[ $((n++)) -eq count ]]; then
        last=" (last)"            # last element, add a note about that
   fi
   printf "%s%s\n" "$x" "$last"
done

Конечно, в вашем случае вы также можете сделать первый элемент исключительным.

0
27.01.2020, 22:08

Теги

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