Проблема здесь заключается в символе !
, который в bash
, когда интерактивен, даже внутри двойных кавычек вызывает расширение истории .
Эта функция взята из csh (, где она на самом деле хуже ), а также встречается в bash и zsh, но в остальном не является стандартной sh
функцией.
В bash
и zsh
, в отличие от csh
, раскрытие истории не происходит внутри одинарных кавычек, так что sed '0,6!d'
будет в порядке. Но sed "0,6!d"
не в порядке. В интерактивных оболочках bash
!d
заменяется последней командой, содержащей d
.
Вы можете удалить специальное значение !
с помощью:
sed "0,$line_number"'!d'
Я лично отключил функцию расширения истории, так как современные оболочки имеют гораздо лучшие интерактивные эквиваленты. Я отключил его в zsh
с помощью set +o banghist
, вы можете отключить его в bash
сset +o histexpand
(на самом деле, zsh
добавил histexpand
в качестве псевдонима к banghist
в 3.1.2 в 1997 году для совместимости с bash
, поэтому set +o histexpand
будет работать и в zsh
). В (t)csh
вы можете отключить расширение истории с помощью set histchars
. Эквивалент histchars=
на самом деле также работает в bash
и zsh
.
Обратите внимание, что адрес 0
является расширением GNU sed
. Портативно вы можете использовать head
вместо (, что также будет более эффективным ):
.
head -n "$line_number"
С sed
, портативно, вы бы использовали:
sed "${line_number}q"
Что также более эффективно, поскольку sed
останавливает чтение после $line_number
-й строки вместо того, чтобы продолжать чтение, но отбрасывает все остальные строки.