从历史记录中提取唯一的单个命令

从历史记录中提取唯一的单个命令

我创建了一个名为 histcopy.txt 的文件,其中包含命令历史记录 ( history > 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 你的记录分隔符可以是换行符或“|”,或“;”,或“$(”,这样管道、替换或链接命令将被分割成记录。然后检查你的第一个字段是否是数字后跟一个点,如果是,则位于行的开头,因此打印第二个字段;否则,打印第一个字段。

相关内容