grep
後でコマンドまたはhead
他のコマンドに渡される前のコマンドの一部を変更するには、常にコマンドラインで矢印を上に向ける必要があることに気づきました。
簡単な例を挙げましょう。dmesg
指定された文字列を検索し、その文字列の最後の5つの項目のみを検索します。
私はそうします:
dmesg | grep -i USB | tail -n 5
ただし、検索語や検索中のコンテンツまたはソースを変更するには、カーソルがその行の対応する部分に戻るまで待ちます。上記の例を次のように表現できるように行末に移動したいと思います。 (私はこれが間違っていることを知っています。)
tail -n 5 < dmesg | grep -i USB
(それで検索できますsda
)
私が言ったように、これは粗いたとえば、私がやりたいことを提案しますが、実際には私がやりたいことではありません。これはdmesg
、and の使用に関するものではなく、これらのプログラム間でやり取りする方法や、「変数」を最後に置く方法に関するものです。grep
tail
これは、DNSクエリの検索時間を取得することによってより詳細に説明できます。
dig google.com | grep msec
google.com
(他のドメインをテストできるように最後に移動します)
grep msec < dig google.com
繰り返しますが、悪い例です。私がもっと話すのは、複数のプログラム間で入力/出力が流れる場合です。
私はパイプとリダイレクトについて基本的にのみ理解していることを認めます。これは次のように要約できます。
- パイプ(
|
)stdout
あるプログラムの入力をstdin
別のプログラムの入力として使用する - リダイレクト(
>
)プログラムをインポートしてstdout
ファイルに入力します(余談:私が考えることができる唯一の確実な場所ではなく、他の場所にリダイレクトできますか?
> /dev/null
または
> /dev/sda
または
> {said file}
しかし、管路プログラム出力はプログラム入力で左から右に進みます。 - リダイレクト(
<
) (私はこれを「入力ファイル」と呼びます)ファイルの内容をインポートし、コマンドラインに入力したように使用します。
答え1
(bash、ksh、zsh)をサポートするシェルでは<()
変換できます。
$ cmd1 | cmd2
入力する
$ cmd2 < <(cmd1)
2つはパイプの側面で同じでなければなりません。 (ただし、2つの形式がプロセスグループや信号などを処理する方法には若干の微妙な違いがあると思います。)
コマンドラインの編集をより良くするには、シェルツールを確認することをお勧めします。たとえば、bashを使用すると、set -o vi
viに似たショートカットを使用したり、vim
より効率的に編集コマンドに直接切り替えたりできます。set -o emacs
emacsショートカットはデフォルトで使用されます(man bash
詳細についてはreadlineを検索してください(/readline
))。
答え2
私はしばしば同じことで迷惑になりますが、それを処理する方法はいくつかあります。
ただ受け入れなさい。時には問題を解決するのに時間を費やす価値はありません。
PSkocikが述べたように、例えば、次のものを使用できます。
tail -n 5 <(dmesg | grep USB)
シェルの編集機能をより上手に使いましょう。たとえば、bash(およびreadlineを使用する他の多くのプログラム)では、それを使用して行の先頭にCtrlA移動し、「単語」を前後に移動してESCf現在の行を編集できます。 $編集で(例:)ESCbCtrl-XCtrl-E
vim
より多くの編集コマンドが利用可能で、readline
.infoファイルに完全に文書化されています。 Debianシステムでは、このreadline-doc
パッケージをインストールしてください。他のディストリビューションには、readlineパッケージ自体にドキュメントが含まれているか、Debianのように別々のものになることがあります。
また、Lynxと同様の経験のために、Lynx Webブラウザをインストールして使用することをお勧めしますpinfo
(私の考えでは、GNUinfo
ブラウザはひどくてほとんど利用できません)。ディストリビューションにまだない場合は、次のことができます。http://pinfo.alioth.debian.org/
readline
一部の人が好むvi
編集モード(デフォルトは同様のモード)もあります。emacs
簡単な場合は、クイック置換を使用できます。たとえば、最後に入力したコマンドが次のような場合です。
dmesg | grep -i USB | tail -n 5
^USB^sda^Enterこれにより、入力によって実行が発生します。
dmesg | grep -i sda | tail -n 5
詳細については、特にセクションを参照してman bash
検索してください。HISTORY EXPANSION
Event Designators
はい。これを繰り返し実行することも迷惑なことになるかもしれません。
- より複雑な場合は、長くて複雑なコマンドパイプラインを使用するのではなく、目的のタスクを実行して実行するシェルスクリプトまたは関数を作成するのが最善です。
たとえば、次の名前のシェルスクリプトを作成しますdmesg-grep
。
#! /bin/bash
# regexp to search for is arg 1. needs to be an extended regexp
# because we're using grep -E aka egrep.
re="$1"
# number of lines to output is optional arg 2 (default 5)
lines=${2:5}
dmesg | grep -iE "$re" | tail -n "$lines"
dmesg-grep usb
その後、またはを実行できますdmesg-grep sda
。
これを頻繁に実行する場合は、bin
ホームディレクトリにサブディレクトリを作成し、それをデフォルトのパス~/bin
(inまたはなど~/.bash_profile
)~/.bashrc
に追加し、その中にスクリプトを保存します。
答え3
これは付随的な答えだと思うかもしれませんが、解決策はコマンドラインで単に変数を使用することです。これはシェルスクリプトにのみ適用されません。たとえば、試行錯誤を通じて複雑な「一行」を開発中であり、次のようになります。
$ some complex command using value 23 at this point
その後、コマンドラインの中央にある値を1つだけ変更しようとします。一度編集すると、追加の編集なしでその行を簡単に呼び出すことができます。
$ a=23
$ some complex command using value "$a" at this point
$ a=37
$ some complex command using value "$a" at this point
$ a=42
$ some complex command using value "$a" at this point
$a
ディレクトリやファイル名など、コマンドに複数の場所が必要な場合に最適です。