履歴から一意の単一コマンドを抽出します。

履歴から一意の単一コマンドを抽出します。

コマンド履歴(history > histcopy.txt)を含むhistcopy.txtというファイルを作成しました。次のように見えます。

 1. l
 2. ls
 3. cat necopy.txt
 4. netstat
 5. cd | ls-l ; grep -i "3" histcopy.txt | echo

すべてのユニークなコマンドを印刷したいです。これまでに実行したコマンドは次のとおりです。

awk '{print $2}' histcopy.txt | sort|uniq`

結果は次のとおりです。

l
ls
cat
netstat
cd

しかし、最後の行(5. cd | ls-l ; grep -i "3" histcopy.txt | echo)には無視して最初のコマンドだけを取るコマンドがたくさんありますcd。現在のコマンドも抽出されるように、どのように書き換えることができますか?このようにして5行目から次も抽出されます。

  • ls-l
  • grep -i "3: histcopy.txt
  • echo

出力リストに別の項目として含めます。

答え1

$ cat histcopy.txt 
 1 l
 2 ls
 3 cat necopy.txt
 4 netstat
 5 cd | ls -l ; grep -i "3" histcopy.txt | echo

$ sed 's/^\s*\S*\s*//' histcopy.txt | tr ';|' '\n' | awk '!seen[$1]++{print $1}'
l
ls
cat
netstat
cd
grep
echo
  • sed 's/^\s*\S*\s*//'history出力からコマンドに関連する初期スペースと数字を削除します。
  • tr ';|' '\n';とを|改行文字に置き換えます。これは現在の問題の説明では機能しますが、代替項目にコマンドなどがある場合は役に立ちません。
  • awk '!seen[$1]++{print $1}'固有コマンド


perl同様のロジックを別々に実装

$ perl -lne 's/^\s*\S+//; (@a)= split/[;|]/; foreach (@a){($k) = /^\s*\K(\S+)/; print $k if !$seen{$k}++}' histcopy.txt 
l
ls
cat
netstat
cd
grep
echo

答え2

続行するには、次の手順を実行しますawk

awk 'BEGIN {RS="\n|\\||;|\\$\\("}
     $1 ~ /^[0-9]+\./ {print $2; next}
     {print $1}' file | sort | uniq

説明する: レコード区切り文字が改行、"|"、";"または、「$(」である可能性があるため、パイプ、置換、またはリンクコマンドがレコードに分割される可能性があることをawkに通知します。次に、最初のフィールドが次のものであることを確認してください。最初のフィールドが印刷され、それ以外の場合は最初のフィールドが印刷されます。

関連情報