Bashプログラミング
 Computer >> コンピューター >  >> プログラミング >> Bashプログラミング

知っておきたいLinux Bash履歴展開の実例15選

知っておきたいLinux Bash履歴展開の実例15選Bashの履歴機能は非常に強力です。履歴展開(history expansion)を効果的に使いこなせるようになれば、Linuxコマンドラインでの作業効率は飛躍的に向上します。

この記事では、以下の3つのBash履歴展開機能を使った15の実例を解説します。

  • イベント指定子(Event Designators):履歴内の特定のコマンドを参照します。「!」で始まります。
  • 単語指定子(Word Designators):履歴エントリ内の特定の単語を参照します。通常はイベント指定子と組み合わせて使い、両者はコロン(:)で区切られます。
  • 修飾子(Modifiers):イベント指定子や単語指定子による置換結果を加工します。

この記事は、連載「Bashチュートリアルシリーズ」の一部です。

ご存じのとおり、すべての履歴エントリを表示するにはhistoryコマンドを使います。過去に実行したコマンドが、履歴テーブル上の番号とともに一覧表示されます。

$ history
1 tar cvf etc.tar /etc/
2 cp /etc/passwd /backup
3 ps -ef | grep http
4 service sshd restart
5 /usr/local/apache2/bin/apachectl restart

Bash履歴のイベント指定子

1. !nで履歴から特定のコマンドを実行する

以前に実行したコマンドをもう一度入力し直す代わりに、履歴番号を指定すれば素早く再実行できます。

たとえば、4番のコマンドを実行するには次のようにします。履歴から4番のコマンドが表示され、そのまま即座に実行されます。

$ !4
service sshd restart

2つ前に入力したコマンドを実行するには、次のようにします。

$ !-2

直前のコマンドを実行するには、次のいずれかを使います。

$ !!

$ !-1

また、デフォルトのemacsモードであれば、<Ctrl>-P を押すことでも前のコマンドへ移動できます。

「set -o vi」でvi風の編集モードを有効にしている場合は、<Esc>-k で前のコマンドに移動できます。

2. !stringと!?stringでキーワードを指定してコマンドを実行する

キーワードを使って、履歴からコマンドを呼び出して実行することもできます。

次の例では、「ps」で始まる過去のコマンドを検索して実行します。この例では、直前のコマンド「ps -ef | grep http」が選択され、実行されます。

$ !ps
ps -ef | grep http

次の例では、「apache」を含む過去のコマンドを検索して実行します。この例では「/usr/local/apache2/bin/apachectl restart」が選択され、実行されます。

$ !?apache
/usr/local/apache2/bin/apachectl restart

3. ^str1^str2^で前のコマンドの文字列を置換する

次の例では、まずlsコマンドでファイルの存在を確認しました。その後、今度はファイルの中身を見たいことに気づいたとします。長いファイル名を打ち直す必要はなく、前のコマンドの「ls」を「cat」に置き換えるだけで済みます。

$ ls /etc/cron.daily/logrotate

$ ^ls^cat^
cat /etc/cron.daily/logrotate

※補足:Bash履歴に関するさらに詳しいヒントは「15 Examples To Master Linux Command Line History」を参照してください。履歴へのタイムスタンプ表示の方法や、HISTTIMEFORMAT、HISTSIZE、HISTFILE、HISTCONTROL、HISTIGNOREといった各種履歴関連の環境変数の使い方を解説しています。

Bash履歴の単語指定子

単語指定子は、新しいコマンドを入力する際に、以前実行したコマンドの引数を流用したい場合に非常に便利です。以下に具体例を示します。

4. :^でコマンドの1番目の引数を取得する

次の例では、「ls -l」コマンドの引数として「!cp:^」を指定しています。「!cp:^」は、「cp」で始まる直前の履歴コマンドを探し、その1番目の引数を取得します。

$ cp /etc/passwd /backup

$ ls -l !cp:^ 
ls -l /etc/passwd

次の例では、直前のコマンドから1番目の引数を取得します。

$ ls -l !!:^

5. :$でコマンドの最後の引数を取得する

次の例では、「ls -l」コマンドの引数として「!cp:$」を指定しています。「!cp:$」は、「cp」で始まる直前の履歴コマンドを探し、その最後の引数を取得します。

$ cp /etc/passwd /backup

$ ls -l !cp:$
ls -l /backup

次の例では、直前のコマンドから最後の引数を取得します。

$ ls -l !!:$

6. :nでコマンドのn番目の引数を取得する

次の例では、「ls -l」コマンドの引数として「!tar:2」を指定しています。「!tar:2」は、「tar」で始まる直前の履歴コマンドを探し、その2番目の引数を取得します。

$ tar cvfz /backup/home-dir-backup.tar.gz /home

$ ls -l !tar:2
ls -l /backup/home-dir-backup.tar.gz

7. :*でコマンドのすべての引数を取得する

次の例では、「ls -l」コマンドの引数として「!cp:*」を指定しています。「!cp:*」は、「cp」で始まる直前の履歴コマンドを探し、そのすべての引数を取得します。

$ cp /etc/passwd /backup

$ ls -l !cp:*
ls -l /etc/passwd /backup

8. !%で直前に検索した単語を参照する

前述のとおり、「!?apache」は「apache」というキーワードを含む過去の履歴コマンドを検索して実行します。

$ /usr/local/apache2/bin/apachectl restart

$ !?apache
/usr/local/apache2/bin/apachectl restart

「!%」は、直前の「?」検索で一致した単語全体を参照します。

たとえば、以前に「?apache」で検索していた場合、「!%」は「/usr/local/apache2/bin/apachectl」という単語全体に一致します。この文脈では「/」も1つの単語の一部として扱われる点に注意してください。

したがって、この状態で次のコマンドを実行すれば、Apacheを停止できます。

$ !% stop
/usr/local/apache2/bin/apachectl stop

9. x-yで引数の範囲を取得する

次の例では、「ls -l」コマンドの引数として「!tar:3-5」を指定しています。「!tar:3-5」は、「tar」で始まる直前の履歴コマンドを探し、3番目から5番目までの引数を取得します。

$ tar cvf home-dir.tar john jason ramesh rita

$ ls -l !tar:3-5
ls -l john jason ramesh

次の例は、2番目以降のすべての引数を取得します。

$ ls -l !tar:2-$

以下の書き方の違いにも注意しておきましょう。

  • !!:* — 直前のコマンドのすべての引数を取得
  • !!:2* — 2番目の引数以降のすべての引数を取得
  • !!:2-$ — 上記と同じ。2番目の引数以降のすべての引数を取得
  • !!:2- — 2番目の引数以降の引数を取得(ただし最後の引数は除く)

Bash履歴の修飾子

修飾子は、以下の例のように単語指定子の後に付けて指定します。

10. :hで末尾のパス名(ファイル名)を削除する

次の例では、「!!:$:h」が直前のコマンドの最後の引数を取り、そこから末尾のパス名を削除します。この場合、ファイル名が取り除かれ、ディレクトリのフルパスのみが残ります。

$ ls -l /very/long/path/name/file-name.txt

$ ls -l !!:$:h
ls -l /very/long/path/name

11. :tで先頭のパス名をすべて削除する

これは前の例の正反対の動作です。

次の例では、「!!:$:t」が直前のコマンドの最後の引数を取り、先頭のパス名をすべて削除します。この場合、ファイル名のみが取得されます。

$ ls -l /very/long/path/name/file-name.txt

$ ls -l !!:$:t
ls -l file-name.txt

12. :rでファイル名の拡張子を削除する

次の例では、「!!:$:r」が直前のコマンドの最後の引数を取り、そこから「.suffix」(ここではファイル名の拡張子)の部分だけを削除します。この場合、「.txt」が取り除かれます。

$ ls -l /very/long/path/name/file-name.txt

$ ls -l !!:$:r
ls -l /very/long/path/name/file-name

13. :s/str1/str2/でsed風の置換を行う

先ほど紹介した「^original^replacement^」の代わりに、以下の例のようにsed風の置換構文をBash履歴で使うこともできます。こちらの方が覚えやすいと感じる人も多いでしょう。「!!」で直前のコマンドを呼び出し、「:s/元の文字列/置換後の文字列/」というsed風の構文で文字列を置換します。

$ !!:s/ls -l/cat/

さらに、以下のようにgフラグ(sフラグと併用)を使えば、グローバル置換が可能です。複数箇所を誤入力してしまい、それらをまとめて修正してコマンドを再実行したい場合に非常に便利です。

次の例では、うっかり(passwdではなく)「password」と2回入力してしまいました。

$ cp /etc/password /backup/password.bak

これを修正するには、次のようなグローバルな履歴置換を実行するだけです。

$ !!:gs/password/passwd/
cp /etc/passwd /backup/passwd.bak

14. :&で直前の置換を素早く繰り返す

上記のようにBash履歴置換を一度成功させていれば、「:&」を使って同じ置換を素早く再実行できます。

別のコマンドでも、またしても「passwd」の代わりに「password」と入力してしまいました。

$ tar cvf password.tar /etc/password

ここで、コマンドを打ち直したり「gs/password/passwd」をやり直したりする代わりに、「:&」を使えば直前の置換をそのまま再利用できます。グローバルに再利用したい場合は「:g&」を使います。

$ !!:g&
tar cvf passwd.tar /etc/passwd

15. :pでコマンドを実行せずに表示だけ行う

複雑な履歴置換を行う際に、実行前に最終的なコマンドの内容を確認したい場合にとても役立ちます。

次の例の「!tar:3-:p」は、実際にはコマンドを実行しません。

「:p」を指定しているため、置換処理だけが行われ、結果となる新しいコマンドが表示されるだけです。Bash履歴展開の結果を確認し、これが意図した通りのコマンドだと分かったら、「:p」を外してもう一度実行すればよいのです。

$ tar cvf home-dir.tar john jason ramesh rita

$ tar cvfz new-file.tar !tar:3-:p
tar cvfz new-file.tar john jason ramesh

  1. 知っておくべき便利なLinux Bashコマンドラインショートカット徹底解説

    この記事では、すべてのLinuxユーザーに役立つBashコマンドラインショートカットを多数紹介します。これらのショートカットを覚えておけば、過去に実行したコマンドの呼び出しや再実行、エディタの起動、コマンドライン上でのテキストの編集・削除・変換、カーソル移動、プロセス制御などを、素早く効率的に行えるようになります。 本記事は、コマンドラインの基本を学び始めたばかりのLinux初心者にとって特に有益ですが、中級者や上級者の方にとっても、意外と知られていない実用的なヒントが見つかるはずです。以下では、Bashのキーボードショートカットをカテゴリ別に分けて解説していきます。 エディタを起動する ター

  2. 【初心者向け】知っておきたいコマンドプロンプトの便利な7つのコツ

    数十年前に時間を巻き戻してみると、コンピューターの操作といえば、コマンドプロンプトのウィンドウでキーを打ち込むことが中心の時代でした。システムにほんの少しの変更を加えるだけでも、あらゆるコマンドを暗記していなければならず、あの地味な白黒のウィンドウを敬遠していた方も多いのではないでしょうか。 コマンドプロンプトは見た目こそ華やかではありませんが、Windows環境において常に重要な役割を担ってきました。使いこなすには多少複雑なコマンドを覚える必要がありますが、Windowsの根幹にアクセスできる最も安全で強力な手段の一つであることに変わりはありません。 現在では日常的にコマンドプロンプトを使