Можно испытать этот мой сценарий. Это позволит Вам или указать файл, или это берет стандартный вход. Можно определить регулярное выражение Python для текста, который Вы хотите выделить. выделенные текстовые значения по умолчанию к неоновому зеленому (эй я использую черный фон!), Но можно изменить цветовой код ANSI.
#!/usr/bin/env python
import sys
import re
def highlight_text(text,pat):
def replacement_funk(matchobj): return '\x1b[42m%s\x1b[0m'%matchobj.group(0)
return re.sub(pat,replacement_funk,text)
if __name__ == '__main__':
if len(sys.argv) == 2:
input = sys.stdin
pat = sys.argv[1]
elif len(sys.argv) == 3:
input = open(sys.argv[2])
pat = sys.argv[1]
else:
sys.stderr.write("colorme pattern [inputfile]")
text = input.read()
print highlight_text(text,pat)
Вот пример.
blessburn@blessburn:/tmp$ cat test.txt | ./colorme.py an
Перспективы организованного вывода войск НАТО из Афганистана перенесли две неудачи, поскольку президент Hamid Karzai потребовал пределов на войска Соединенных Штатов, и Талибан остановил мирные переговоры.
blessburn@blessburn:/tmp$ ./colorme.py '(Af.*? |NA[\w]{2})' test.txt
Перспективы организованного вывода войск НАТО из Афганистана перенесли две неудачи, поскольку президент Hamid Karzai потребовал пределов на войска Соединенных Штатов, и Талибан остановил мирные переговоры.
Ваша основная проблема состоит в том, что последняя команда в конвейере работает в подоболочке, как все другие команды в конвейере. Дело обстоит так в большинстве оболочек. ATT ksh и zsh являются исключениями: они выполняют последнюю команду конвейера в родительской оболочке.
Начиная с удара 4.2, можно сказать удару вести себя как ksh и zsh путем установки lastpipe
опция.
#!/bin/bash
USERS=()
shopt -s lastpipe
w | awk '{if(NR > 2) print $1,$2,$3}' | while read line; do
USERS+=("$line")
done
echo ${#USERS[@]}
С другой стороны, можно использовать замену процесса вместо канала, так, чтобы read
управляйте выполнениями в основном процессе оболочки.
#!/bin/bash
USERS=()
while read line; do
USERS+=("$line")
done < <(w | awk '{if(NR > 2) print $1,$2,$3}')
echo ${#USERS[@]}
С другой стороны, можно использовать портативный подход, который работает в оболочках, которые не имеют процесса susbtitution, ни ksh/zsh поведения, такого как Bourne, тире и pdksh. (Вам все еще нужно (фунт) ksh, удар или zsh для массивов.) Выполненный все, что требует данных из конвейера в конвейере.
#!/bin/bash
USERS=()
shopt -s lastpipe
w | awk '{if(NR > 2) print $1,$2,$3}' | {
while read line; do
USERS+=("$line")
done
echo ${#USERS[@]}
}
С shopt -s lastpipe
можно принять последнее управление конвейером в текущую среду оболочки. Это решает Вашу проблему. Я предполагаю, что эта функция не всегда была в ударе, так избегайте его, если Вы хотите широко совместимый код.
Совместимая альтернатива:
export_array="$(w | awk '{if(NR > 2) print $1,$2,$3}' |
{ USERS=(); while read line; do
USERS[]="$line"
done
declare -p USERS; } )"
eval "$export_array"
+=
нотация была добавлена в последних версиях удара. Обе команды делают то же.
– Hauke Laging
08.06.2013, 02:40
Массивы Bash являются одномерными. Если Вы хотите держать заказанный отдельные значения для каждой строки, одно решение состоит в том, чтобы использовать ассоциативные массивы. Сырой пример:
Также будьте осторожны с теми прописными именами переменной, поскольку они могут столкнуться с переменными среды.
#!/bin/bash
declare -i i=0 j=0
declare -A w
while read -r user tty from _;do
((++i > 2)) || continue
w["$j.user"]="$user"
w["$j.tty"]="$tty"
w["$j.from"]="$from"
((++j))
done < <(w)
for ((i = 0; i < j; ++i)); do
printf "entry %-2d {\n %-5s: %s\n %-5s: %s\n %-5s: %s\n}\n" \
"$i" \
"user" "${w[$i.user]}" \
"tty" "${w[$i.tty]}" \
"from" "${w[$i.from]}"
done
для устройства хранения данных в массивах удара, с помощью разделителя кроме пространства часто более просто.
readarray -s2 -t my_w_array < <(w | awk '{ print $1":"$2":"$3 }')
можно затем разделить его при печати его, как:
printf '%s\n' "${my_w_array[@]//:/ }"