sh
(как в sh
спецификация языка), не идет со строчным редактором. Терминальные драйверы имеют элементарный строчный редактор, которые позволяют, чтобы клавиша Backspace и несколько других ключей отредактировали вводимую строку, но обычно не клавиши со стрелками.
Можно вставить значение по умолчанию в терминальный входной буфер драйвера с помощью TIOCSTI
ioctl как:
printf 'Please enter the value: '
value=the-default
perl -MPOSIX -e 'require "sys/ioctl.ph"; tcflush 0,2;
ioctl(STDIN, &TIOCSTI, $_) or die "$!\n"
for split "", join " ", @ARGV' "$value"
IFS= read -r value
На read
, содержание $value
(the-default
) будет вставлен как будто введенный.
Теперь, если Вы хотите более усовершенствованный строчный редактор, любят обеспеченный libreadline
где можно использовать клавиши со стрелками, можно использовать вещи как rlwrap
(не стандартная команда, хотя):
value=the-default
value=$(rlwrap -S 'Please enter the value: ' -P "$value" -o cat)
rlwrap
обычно используется для добавления a readline
- как строчные редакторы к приложениям, которые не имеют того. Выше мы добавляем строчный редактор к cat
, и использование его в одноразовом режиме (-o
), так, чтобы cat
возвраты после одной строки вводятся (хотя можно все еще ввести больше чем одну строку с Ctrl+V, Ctrl-J как в bash
.
Если Вы готовы использовать нестандартные оболочки, zsh
или bash
имейте builtins для того использования их собственного строчного редактора.
В zsh
:
value=the-default
vared -p 'Please enter the value: ' value
В bash
:
value=the-default
IFS= read -re -i "$value" -p 'Please enter the value: ' value
Это сработало:
sed -n '/eth/{n;p;n;n;n;p;}' file
eth
n;
: пропустить строку, p;
: выведите строкуn;n;n;
: пропустите 3 строки и выведите еще разEdit:
Это выведет строку выше, строку после и строку после 3 строк:
sed -n -e '/eth/{x;1!p;g;$!n;p;n;n;n;p;D;}' -e h file
И ваш второй вопрос: Я думаю, что вы не сможете набрать 20 раз команду n;
...
Попробуйте эту awk-команду,
$ awk '$1~/^eth/ {getline; print; getline; getline; getline; print}' file
inet addr:10.179.113.125 Bcast:10.179.113.127 Mask:255.255.255.248
RX packets:1169385 errors:0 dropped:0 overruns:0 frame:0
inet addr:10.254.4.1 Bcast:10.254.4.255 Mask:255.255.255.0
RX packets:3806158038 errors:0 dropped:23193484 overruns:0 frame:0
Обновление:
$ awk '$1~/^eth/ {print previous; getline; print; getline; getline; getline; print}{previous=$0}' file
Mon Jun 9 00:11:47 CST 2014
inet addr:10.179.113.125 Bcast:10.179.113.127 Mask:255.255.255.248
RX packets:1169385 errors:0 dropped:0 overruns:0 frame:0
Tue Jun 10 05:11:47 CST 2014
inet addr:10.254.4.1 Bcast:10.254.4.255 Mask:255.255.255.0
RX packets:3806158038 errors:0 dropped:23193484 overruns:0 frame:0
Есть несколько способов. Пожалуйста, обратите внимание на следующие вопросы по SO:
Вот другой подход, который использует Perl и дает вам больше гибкости для того, какие строки вы хотите напечатать:
perl -n00E '
@eth_records= grep {/eth/} split/(?=>Mon|Tue|Wed|Thu|Fri|Sat|Sun)/;
@lines_to_print = qw{1 3 6};
map { $_-- } @lines_to_print;
$sep = "-"x80;
for(@eth_records){
say $sep;
say for (split/\n/)[ @lines_to_print ];
say $sep
}' your_file
Это разбивает файл на записи в строках, начинающихся с имени дня, и печатает 1-ю 3-ю и 6-ю строки всех записей, соответствующих /eth/
Обратите внимание, что он загрузит весь ваш файл в память, так что избегайте этого, если ваш файл большой.
Вот несколько предложений:
grep
grep -P 'CST | inet | RX p' file
Это напечатает все строки, содержащие CST
или inet
, за которыми следует пробел или RX pa
. -P
активирует Perl-совместимые регулярные выражения, что позволяет нам использовать |
как логическое ИЛИ. Вы также можете добиться того же с помощью любого из
grep -E 'CST | inet | RX p' file
или
grep 'CST \ | inet \ | RX p' файл
sed
sed -n '/ CST \ | inet \ | RX p / p' файл
sed -rn '/ CST | inet | RX p / p' файл
Та же идея, что и выше, -n
подавляет печать любых строк, а // p
означает печать тех строк, которые соответствуют шаблону.
perl
Вы можете использовать тот же подход в Perl:
perl -ne 'print if / CST | inet | RX p /' file
Или вы можете сделать что-то вроде
perl -ne '$ k = 1 if / CST /; напечатать, если $ k == 1 || $ k == 3 || $ k == 6; $ k ++ 'файл
Здесь переменная $ k
устанавливается в 1, если строка соответствует CST
, и увеличивается на единицу после чтения каждой строки. Строка затем печатается, если $ k
имеет значение 1,3 или 6. Это более расширяемый подход.
В качестве альтернативы, если вы знаете номера строк, которые хотите напечатать, было бы просто распечатать их напрямую ( $.
- текущий номер строки):
perl -ne 'print if $ . == 1 || $. == 3 || $. == 6 || $. == 11 || $. == 13 || $. == 16 'файл
или, более идиоматично:
perl -ne '@ d = (1,3,6,11,13,16); напечатать, если файл $.~~@d '
Наконец, вы также можете загрузить весь файл в память и распечатать только те строки, которые вам нужны:
perl -e '@F = <>; напечатать @F [0,2,5,10,12,15] 'файл
awk
Вы можете использовать те же базовые подходы в awk
, где NR
- текущий номер строки:
awk '/ CST | inet | RX p /' файл
или
awk '{if (/ CST /) {k = 1} if (k == 1 || k == 3 || k == 6) {print} k ++;}' файл
или
awk 'NR == 1 || NR == 3 || NR == 6 || NR == 11 || NR == 13 || NR == 16' файл