Часть 1
Просто d
выберите 13-ую строку:
sed '13d' <file.txt
И общий способ сделать дополнение вышеупомянутого:
sed '13!d' <file.txt
Часть 2
Потому что это можно сделать:
sed -n ':a;${P;q};N;4,$D;ba' <file.txt
Обратите внимание, что 4
это на один номер больше, чем вам нужно. Так что, если бы вы хотели последнюю 10-ю строчку, это было бы 11
.
Тестирование с seq
:
$ seq 100 | sed -n ':a;${P;q};N;4,$D;ba'
98
$
Попытка объяснения
:a # define label a
${ # match the last line
P # print the first line of the pattern space
q # quit
}
N # match all lines: append the next line to the pattern
4,${ # match the range of lines 4 to the end of the file
D # delete the first line of the pattern space
}
ba # match all lines: jump back to label a
Ценное дополнение Гленна Джекмана:
Это была «только N-я линия». Вот "все НО-я строка":
sed -n ':a;${s/^[^\n]*\n//;p;q};N;4,${P;D};ba'
работает с GNU Sed, \n
последовательность может не работать с другими SED.
Я попробовал это с помощью BSD sed (OSX) и обнаружил, что он не совсем работает в приведенной выше форме. Проблемы, как представляется:
;
используется для разделения строк, как правило, работает, но не работает после метки
- BSD sed, кажется, требует
;
после последней команды в однострочной {}
группе команд, тогда как GNU sed не делает
\n
обычно может использоваться в регулярном выражении, но, очевидно, не в []
выражении в скобках. Таким образом, чтобы исключить символы новой строки, мы можем использовать что-то вроде [[:alnum:][:punct:][:graph:][:blank:]]
этого, хотя это может исключать другие символы (особенно другие управляющие символы).
Так что это попытка более независимой от платформы версии:
sed -n ':a
${s/^[[:alnum:][:punct:][:graph:][:blank:]]*\n//p;q;};N;4,${P;D;};ba'
Похоже, это работает под OSX и Ubuntu.
head
/tail
решение намного медленнее, чемsed
решение. Спасибо хоть.head
/tail
) оптимизированы для того, что они делают.