Во-первых, вы всегда должны заключать выражение grep в кавычки, так как попытки запомнить, какая оболочка что делает с каким специальным символом - это мучение:
grep -o -E '[x]{3,4}' testfile
Во-вторых, grep
найдет минимальное совпадение, это просто, так что с радостью найдет 3 или 4 пробега x
в более длинном пробеге x
s. Чтобы предотвратить это, необходимо какое-то граничное условие, чтобы не совпадало с подмножеством более длинного пробега. grep
с поддержкой PCRE может использовать обходные пути нулевой ширины для достижения этого:
(echo xxx; echo xxxxxx) | grep -P '(?<!x)xxx(?!x)'
При удалении s
вы удаляете первый s
в строке $HOSTLIST
. Скорее всего, это будет не тот s
, который вы хотите удалить (примечание localhot
в выходных данных ).
Лучше использовать массив и создать массив из подходящих хостов, может быть что-то вроде
hostlist=( localhost sdfsd sdfs s fsdf localhost sdfs fsdf sdf 127.0.0.1 )
for h in "${hostlist[@]}"; do
if timeout 3 bash -c "</dev/tcp/$h/22" 2>/dev/null; then
ok+=( "$h" )
fi
done
printf 'Ok host: %s\n' "${ok[@]}"
Вы также можете сделать это, перебирая индексы массива (${!hostlist[@]}
, обратите внимание на !
), а не значения (${hostlist[@]}
), а затем используя unset
для удаления нежелательные индексы массива.
например, на основе ответа @Kusalananda:
hostlist=( localhost sdfsd sdfs s fsdf localhost sdfs fsdf sdf 127.0.0.1 )
for h in "${!hostlist[@]}"; do
if ! timeout 3 bash -c "</dev/tcp/${hostlist[$h]}/22" 2>/dev/null; then
unset hostlist[$h]
fi
done
printf 'Ok hosts: %s\n' "${hostlist[@]}"
или, если у вас установлен netcat
, вы можете использовать nc
вместо bash /dev/tcp
, встроенный -в (должен быть немного быстрее, чем разветвление timeout
и bash
для каждого хозяин):
hostlist=( localhost sdfsd sdfs s fsdf localhost sdfs fsdf sdf 127.0.0.1 )
for h in "${!hostlist[@]}"; do
if ! nc -w 3 "${hostlist[$h]}" 22 >& /dev/null; then
unset hostlist[$h]
fi
done
printf 'Ok hosts: %s\n' "${hostlist[@]}"
Если вам больше не нужно делать что-либо внутри оператора if
/ then
, вы можете сократить его еще больше:
hostlist=( localhost sdfsd sdfs s fsdf localhost sdfs fsdf sdf 127.0.0.1 )
for h in "${!hostlist[@]}"; do
nc -w 3 "${hostlist[$h]}" 22 >& /dev/null || unset hostlist[$h]
done
printf 'Ok hosts: %s\n' "${hostlist[@]}"