Препятствуйте тому, чтобы экран выключил (в консоли)
$ setterm -blank 0 -powerdown 0
Кроме того, можно отключить консоль, очищающую постоянно использование следующей команды:
# echo -ne "\033[9;0]" >> /etc/issue
Это может даже быть сделано только с 'bash'
, без 'sed'
, 'awk'
или 'perl'
:
echo -e 'one two three\nfour five six\nseven eight nine' |
while IFS=" " read -r -a line; do
nb=${#line[@]}
echo ${line[$((nb - 1))]}
done
Попытка:
echo -e 'one two three\nfour five six\nseven eight nine' | awk '{print $NF}'
ps -ef | awk '{ print $NF }'
имел некоторые строки, усеченные...), Perl не имеет того ограничения. (gnu.org/software/autoconf/manual/autoconf-2.67/html_node / …: "Традиционный Awk имеет предел 99 полей в записи. Так как некоторые реализации Awk, как Tru64, разделяют вход, даже если Вы не обращаетесь ни к какому полю в сценарии, для хитрости этой проблемы, установите 'FS' на необычный символ и используйте разделение".)
– Olivier Dulac
29.01.2014, 10:48
awk
реализации имеют то ограничение? Я никогда не видел его. Мой mawk
будет дросселировать на 32768
но мой gawk
и igawk
может иметь дело с миллионами счастливо. Даже мой busybox's awk
может иметь дело с миллионами. Я никогда не сталкивался awk
это не может иметь дело с 100 полями, это - крошечное количество, в конце концов. Вы уверены, что информация все еще релевантна? Даже на Солярисе?
– terdon♦
16.10.2015, 12:15
Это легче, чем Вы думаете.
$ echo one two three | awk '{print $NF}'
three
Это может также быть сделано с помощью 'sed'
:
echo -e 'one two three\nfour five six\nseven eight nine' | sed -e 's/^.* \([^ ]*\)$/\1/'
Обновление:
или проще:
echo -e 'one two three\nfour five six\nseven eight nine' | sed -e 's/^.* //'
Или использование cut
:
echo -e 'one two three\nfour five six\nseven eight nine' | cut -f 3 -d' '
хотя это не удовлетворяет 'общее решение' требование. Используя rev
дважды мы можем решить это также:
echo -e 'one two three\nfour five six\nseven eight nine' | rev | cut -f 1 -d' ' | rev
rev
не работает с 'широкими' символами, только единственные байта, насколько я знаю.
– Marcin
19.07.2012, 20:47
Используя awk
можно сначала проверить, существует ли по крайней мере один столбец.
echo | awk '{if (NF >= 1) print $NF}'
echo 1 2 3 | awk '{if (NF >= 1) print $NF}'
В perl это может быть сделано следующим образом:
#!/usr/bin/perl
#create a line of arbitrary data
$line = "1 2 3 4 5";
# splt the line into an array (we call the array 'array', for lolz)
@array = split(' ', $line);
# print the last element in the array, followed by a newline character;
print "$array[-1]\n";
вывод:
$ perl last.pl
5
$
Вы также можете пройтись по файлу - это пример сценария, который я написал, чтобы разобрать файл budget.dat
пример данных в budget.dat:
Rent 500
Food 250
Car 300
Tax 100
Car Tax 120
Mag Subscription 15
(вы можете видеть, что мне нужно было захватить только "последнюю" колонку, а не только 2)
Сценарий:
#!/usr/bin/perl
$budgetfile = "budget.dat";
open($bf, $budgetfile)
or die "Could not open filename: $filename $!";
print "-" x 50, "\n";
while ( $row = <$bf> ) {
chomp $row;
@r = split (' ', $row);
print "$row ";
$subtotal += $r[-1];
print "\t$subtotal\n";
}
print "-" x 50, "\n";
print "\t\t\t Total:\t$subtotal\n\n";
Попробуйте grep
(короче / проще, но в 3 раза медленнее, чем awk
из-за использования регулярного выражения):
grep -o '\S\+$' <(echo -e '... seven eight nine')
Или ex
(еще медленнее, но он печатает весь буфер после завершения, более полезно, когда его нужно отсортировать или отредактировать на месте):
ex -s +'%s/^.*\s//g' -c'%p|q!' <(echo -e '... seven eight nine')
ex +'%norm $Bd0' -sc'%p|q!' infile
Чтобы изменить на месте, замените -sc '% p | q!'
с -scwq
.
Или bash
:
while read line; do arr=($line); echo ${arr[-1]}; done < someinput
Учитывая сгенерированный файл размером 1 ГБ через:
$ hexdump -C /dev/urandom | rev | head -c1G | pv > datafile
Я выполнил анализ статистики времени (пробежал ~ 3 раза и взял наименьшее значение, протестировано на ОС MBP X):
с использованием awk
:
$ time awk '{print $ NF}' datafile> / dev / null
real 0m12.124s
user 0m10 .704s
sys 0m0.709s
с использованием grep
:
$ time grep -o '\ S \ + $' datafile> / dev / null { {1}} real 0m36.731s
user 0m36.244s
sys 0m0.401s
$ time grep -o '\ S * $' datafile> / dev / null
real 0m40.865s
user 0m39.756s
sys 0m0.415s
с использованием perl
:
$ time perl -lane 'print $ F [-1]' файл данных> / dev / null
real 0m48.292s
user 0m47.601s
sys 0m0.396s {{1 }}
с использованием rev
+ cut
:
$ time (rev | cut -d '' -f1 | rev) / dev / null {{1 }} $ time rev файл данных | вырезать -d '' -f1 | rev> / dev / null
real 1m10.342s
user 1m19.940s
sys 0m1.263s
с использованием ex
:
$ time ex + '% norm $ Bd0_' -sc '% p | q!' datafile> / dev / null
real 3m47.332s
user 3m42.037s
sys 0m2.617s
$ time ex + '% norm $ Bd0' -sc '% p | q!' файл данных> / dev / null
real 4m1.527s
user 3m44.219s
sys 0m6.164s
$ time ex + '% s /^.* \ s // g '-sc'% p | q! ' datafile> / dev / null
real 4m16.717s
user 4m5.334s
sys 0m5.076s
с использованием bash
:
$ время чтения строки; do arr = ($ line); эхо $ {arr [-1]}; done / dev / null
real 9m42.807s
user 8m12.553s
sys 1m1.955s
... | while read -r line; do echo ${line##* }; done
– glenn jackman 20.07.2011, 22:21bash
индекс массива является предметом арифметической оценки, таким образом,echo ${line[nb - 1]}
достаточно. Как говорящий оbash
, можно просто пропустить “nb” вещи:echo ${line[-1]}
. Более портативная альтернатива для позже:echo ${line[@]: -1]}
. (См. комментарий Stephane Chazelas к отрицательным индексам в другом месте.) – manatwork 18.03.2013, 14:04