Как распечатать только последний столбец?

Согласно: https://wiki.archlinux.org/index.php/Display_Power_Management_Signaling#DPMS_Interaction_in_a_console_with_setterm

Препятствуйте тому, чтобы экран выключил (в консоли)

$ setterm -blank 0 -powerdown 0

Кроме того, можно отключить консоль, очищающую постоянно использование следующей команды:

# echo -ne "\033[9;0]" >> /etc/issue

25
21.07.2011, 00:32
9 ответов

Это может даже быть сделано только с '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
6
27.01.2020, 19:40
  • 1
    Хм, или также, принятие Вашего входа на самом деле разделено пробелом: ... | while read -r line; do echo ${line##* }; done –  glenn jackman 20.07.2011, 22:21
  • 2
    @glenn: Это было моей первой идеей, но когда я прочитал руководство 'чтения', я видел эту функцию массива, которую я нашел полезным. Это может также быть легко изменено для предоставления любого поля, индексированного справа. –  jfg956 21.07.2011, 10:54
  • 3
    bash индекс массива является предметом арифметической оценки, таким образом, echo ${line[nb - 1]} достаточно. Как говорящий о bash, можно просто пропустить “nb” вещи: echo ${line[-1]}. Более портативная альтернатива для позже: echo ${line[@]: -1]}. (См. комментарий Stephane Chazelas к отрицательным индексам в другом месте.) –  manatwork 18.03.2013, 14:04

Попытка:

echo -e 'one two three\nfour five six\nseven eight nine' | awk '{print $NF}'
54
27.01.2020, 19:40
  • 1
    I updateted Q –  LanceBaynes 20.07.2011, 20:28
  • 2
    обратите внимание на то, что awk ограничен 99 полями...:/, Это просто кусает меня в прошедшие дни ( 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
  • 3
    @OlivierDulac, что awk реализации имеют то ограничение? Я никогда не видел его. Мой mawk будет дросселировать на 32768 но мой gawk и igawk может иметь дело с миллионами счастливо. Даже мой busybox's awk может иметь дело с миллионами. Я никогда не сталкивался awk это не может иметь дело с 100 полями, это - крошечное количество, в конце концов. Вы уверены, что информация все еще релевантна? Даже на Солярисе? –  terdon♦ 16.10.2015, 12:15
  • 4
    @terdon, см. ссылки в моем комментарии ^^ (и верьте мне, некоторая система "прежней версии" может пережить loooooooog время в некоторых средах. на некоторых, tar hapilly извлечение к "/", удар не имеет некоторых полезных builtins (ни $BASH_SOURCE, например), awk дроссель на NF> 99, и т.д.... :(), –  Olivier Dulac 16.10.2015, 16:10
  • 5
    @OlivierDulac. Я просто не столкнулся с ним. Я надеюсь, что это очень редко сегодня, с тех пор 99 крошечное количество. Довольно понятный –  terdon♦ 17.10.2015, 01:28

Это легче, чем Вы думаете.

$ echo one two three | awk '{print $NF}'
three
14
27.01.2020, 19:40

Это может также быть сделано с помощью '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/^.* //'
5
27.01.2020, 19:40
  • 1
    проще лучше! –  mdpc 21.07.2011, 00:45
  • 2
    @mdpc: Я соглашаюсь, но поскольку более сложное решение было уже отправлено, я решил сохранить его. –  jfg956 21.07.2011, 10:50
... | perl -lane 'print $F[-1]'
6
27.01.2020, 19:40

Или использование 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
5
27.01.2020, 19:40
  • 1
    я не думаю 'версия', может быть найден на всем Unix (AIX, Солярис...) или установлен на всем Linux, но хорошем альтернативном решении. –  jfg956 21.07.2011, 11:34
  • 2
    +1 для двойной версии, но как примечание стороны, 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}'
2
27.01.2020, 19:40

В 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";
1
27.01.2020, 19:40

Попробуйте 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 
     
11
27.01.2020, 19:40

Теги

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