特定のパターンと一致しないファイルのすべての行を見つけようとします。
しばらく私はコマンドが重複するhistory
GNU(バージョン4と5)を使用するのにbash
問題がありました。次のような行が.bashrc
あるからだと思います。
PROMPT_COMMAND="history -a; history -n; $PROMPT_COMMAND"
screen
ターミナルマルチプレクサ(および/または)を使用しているため、上記のコマンドtmux
は複数回実行されますecho $PROMPT_COMMAND
。history -a; history -n; history -a; history -n;
場合によっては(特に別のウィンドウ/ウィンドウ/フレーム/バッファで同時に作業を実行したとき)、最後に入力したコマンドが私にありました~/.bash_history
。
#1596110297
yadm list -a | xargs -t ls -l
yadm list -a | xargs -t ls -l
言うまでもなく、これは迷惑です。 (希望的に)問題の解決策を見つけましたが 修正:この問題は解決されていませんhistory
(コマンドをに変更してPROMPT_COMMAND="history -a; history -n
)history
。
今、重複したアイテムを削除したいと思います。
#
だから私は現在、それで始まる行とそれに続く行を除くすべてにタグを付ける正規表現を見つけようとしています。私の最初のアイデアは、grep -v
(選択反転)とgrep -A 1
(パターン一致後に追加の行を取得する)を組み合わせることでした。しかし、
grep -v "^#" -A 1 ~/.bash_history
期待していた結果が得られませんでした。
私の質問は:を使ってこれを行う方法を知っている人はいますかgrep
?それ以外の場合:これを行うために他のツール(sed
、、...)をどのように使用できますかawk
?
答え1
私が理解したのは、grep -v "^#" -A 1
ハッシュ記号で始まるのではなく、各行の後に1行ずつ印刷することです。ただし、反対の結果が必要ない場合は、次の行を印刷してください。するポンド記号で始まり、行で始めますか?
テストファイルが与えられたら:
#123
echo this
echo this
#456
echo that
echo that
echo that
#789
echo third
grep -A1 ^# history.txt |grep -vxFe --
印刷:
#123
echo this
#456
echo that
#789
echo third
2番目は、grep
グループ区切りなしで印刷することですgrep -A
。
または、uniq history.txt
同じ行の各連続グループから1つだけを印刷する必要があります。
答え2
Rakuを使う(古いPerl6)
これは、さまざまなスクリプト言語で使用できる「トリガー」演算子の作業のようです。以下はRakuプログラミング言語(以前のPerl6)を使った答えです。まず、より広いテストファイルを作成します。
$ cat repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
B_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
D_yadm list -a | xargs -t ls -l
E_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
G_yadm list -a | xargs -t ls -l
H_yadm list -a | xargs -t ls -l
I_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5
fff
Rakuのトリガー演算子を使用して、「sedに似た」動作を達成するコード行を作成します。正規表現では、^^
リテラル "#"文字が(行の先頭に)表示される最初の行に対してキャプチャがオンになっています。オンにすると、キャプチャは最初の正規表現を無視し、2番目の正規表現を評価し、^^
「#」文字が欠落している(行の先頭に)行に一致するものを見つけたときに閉じます。 「負の」正規表現は、次のコードで実装されています<-[#]>
。これは負の「列挙文字クラス」であり、Raku言語の実際の機能です。
$ raku -ne '.put if /^^ "#" / fff /^^ <-[#]> /;' repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5
実際、最初の正規表現(中位演算子の左側fff
)は、<+[#]>
より並列な構成を可能にするために肯定的な「列挙文字クラス」を使用して作成できます。
$ raku -ne '.put if /^^ <+[#]> / fff /^^ <-[#]> /;' repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5
また、1つ以上の数字が続く先行する「#」を一致させるか拒否して正規表現を改善できるようです。つまり<digit>+
、以下を参照してください。
$ raku -ne '.put if /^^ <+[#]> <digit>+ / fff /^^ <-[#]> <-digit>+ /;' repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5
[上記のコードはすべて、B、D、E、G、H、Iで始まる重複行を削除します。私が気づいた唯一の珍しいことは、2つの連続したターゲット行(「#1596110297」など)が出力に表示されることです。しかし、入力ファイルにこれらの連続した行が含まれているかどうかはわかりません。