Я столкнулся с этим только что. Есть довольно простое решение, которое сработало для меня. Я хотел использовать массив, содержащий имя устройства и позицию на экране, чтобы отобразить карту клавиш для устройства. Я сделал следующее :Я объединил имя устройства и соответствующую позицию на экране в одну строку, используя разделитель (, в моем случае я использовал.
)который, как я знал, не появится ни в одном из моих значений. Затем я использовал cut
, чтобы разбить составные значения на их компоненты. при необходимости. Возможно, есть более чистый и простой способ сделать это, но это просто для того, чтобы показать, что вы можете создать многомерный массив в некотором роде в bash, даже если он его не поддерживает :
.
#!/bin/bash
# List of devices and screen positions for key maps.
DEV_LIST=( g13.+2560+30 g510s.+3160+30 g502.+2560+555 )
# This just echoes the device name and the screen position.
for DEV in "${DEV_LIST[@]}"; do
DEVICE=$(echo $DEV | cut -f1 -d.)
SCREEN_POSITION=$(echo $DEV | cut -f2 -d.)
echo "$DEVICE"
echo "$SCREEN_POSITION"
done
exit
Это чем-то похоже на ответ Coop.Computer .
вы можете повторить эту последовательность, чтобы получить диапазон переменных:
#!/bin/bash
LINES=1
LASTLINE=10
for i in $(seq $LINES $LASTLINE )
do
echo $i
done
выход:
1
2
3
4
5
6
7
8
9
10
LASTLINE=$(grep -P '### Stop marker ###' file.txt | wc -l)
Это скажет вам сколько строк соответствует этому шаблону, но не покажет, где они находятся. Если в файле есть один маркер, возвращается 1
. Вам нужно будет использовать что-то вроде grep -n
(--line-number
), чтобы получить номера строк.
file=sed -n $i'p' file.txt
Вероятно, это должно быть file=$(sed...)
, то есть с подстановкой команды для захвата вывода sed
. Но если вы делаете это в цикле, вы читаете весь файл для каждой итерации цикла, глупая трата времени, и если файл длинный, это займет целую вечность.
Вот в чем вопрос Почему использование цикла оболочки для обработки текста считается плохой практикой? , ссылка на которую была здесь ранее. Обратите внимание, что плохой практикой является обработка , изменение текста. Выполнение команд на основе некоторых данных в файле с использованием оболочки вполне нормально; оболочка существует для запуска команд.
Итак, просто прокрутите файл один раз и обнаружите маркер остановки в оболочке:
#!/bin/bash
i=0
while IFS= read -r line; do
if [[ $line == '### Stop marker ###' ]]; then
break;
fi
i=$((i + 1))
echo "line $i, do some stuff with '$line'"
done < file.txt
([[.. ]]
— это кш -изм. Его можно заменить на case
в оболочке POSIX.)
Или пусть какой-нибудь внешний инструмент обработки текста обрабатывает маркер остановки, а оболочка просто запускает команды:
#!/bin/sh
i=0
< file.txt sed -n -e '/### Stop marker ###/q' -e p |
while IFS= read -r line; do
i=$((i + 1))
echo "line $i, do some stuff with '$line'"
done
Если вы действительно хотите выполнить цикл в стиле for (i = 0; i < end; i++)
, вы можете сначала прочитать весь файл в массив, но если вам не нужно произвольный доступ к строкам, это совершенно не нужно. Потоковая передача через файл гораздо более естественна.