sedに変数を渡すときに二重引用符を使用する必要があることを知っています。したがって、sedを使用して行番号付きファイルの行を表示するとき:
sed '894!d' cloud.cpp
私はうまくいきましたが、行番号894をsedに変数として渡したいので、次のことを試しました。
lnum=894
sed "$lnum!d" cloud.cpp
ただし、同じ構文を使用する単一引用符も機能しません。
sed "894!d" cloud.cpp
それでは、この場合、どのように変数をsedに渡すことができますか?
答え1
変数に数字のみが含まれている場合、実行している操作は正しいものです。
sed "$lnum!d" cloud.cpp
sed
通常、シェル変数を渡すには、次をお読みください。この回答。
今、この場合は正しく行いましたが、まだ機能しません。これはシェルによるものbash
です。これらのシェルは、(この機能は元々提供されており、後でコピーされる)とマークされている歴史的な拡張をサポートしています。zsh
csh
!
csh
bash
zsh
では、対話型セッションで履歴拡張がデフォルトbash
でzsh
有効になっており、二重引用符で囲まれています。
存在するzsh
:
$ seq 10 | sed "10!d" # <-- press enter
$ seq 10 | sed "10dash"
これはdash
私の歴史上で始まる最も最近の命令ですd
。
存在するbash
:
$ seq 10 | sed "10!d"
bash: !d": event not found
.bashで始まるbashレコードには何もないからですd
。
履歴拡張をオフにできます。
set +H
または:
set +o histexpand
一緒にするbash
:
set -K
または:
setopt nohistexpand
存在するzsh
。
より移植可能な方法のために、シェルオプションに頼らずにいつでも次のことができます。
sed "$lnum"\!d cloud.cpp
これにより、シェルは文字通り!
処理されます。
答え2
前述のように、文字列に一重引用符を使用すると、その内容は文字通り処理されるため、二重引用符を使用する必要があります。しかし、あなたの場合、パターンと変数の組み合わせがあります。したがって、パターンには一重引用符を、変数には二重引用符を使用する必要があります。
sed "$lnum"'!d' cloud.cpp
答え3
どのシェルを使用しているのか言及していません。以下の回答は次のとおりですbash
。
シェルで履歴拡張をトリガしています。からman bash
:
!string
文字列で始まる履歴リストの現在位置より前の最新コマンドを参照します。
奇妙なことは次のとおりです。
!
有効にすると、二重引用符内に表示される内容がバックスラッシュを使用してエスケープされていない限り、履歴拡張が行われます。前のバックスラッシュは!
削除されません。
だから私はそれらを個別に引用するのがおそらく最良の解決策だと思います。
sed "$lnum"'!d' cloud.cpp
これも動作します(キャラクターを保存します):
sed "$lnum"\!d cloud.cpp
これも機能します(二重引用符を好む場合):
sed "$lnum""!""d" cloud.cpp