乐趣区

关于tools:使用-Shell-进行数据整理学习笔记

写在后面:本篇内容来自于 MIT 推出的课程:计算机教育中缺失的一课,这门课程介绍了命令行、弱小的文本编辑器的应用、应用版本控制系统提供的多种个性等等。中文课程主页:https://missing-semester-cn.github.io/

本篇为课程的第 4 节,主题为数据整顿。

大多数状况下,数据整顿须要您可能明确哪些工具能够被用来达成特定数据整顿的目标,并且明确如何组合应用这些工具。

  • 获取服务器日志:ssh myserver journalct > journal
  • sed:应用正则表达式进行替换,用法,sed 's/.*Disconnected from //',将这一部分替换为空。s/REGEX/SUBSTITUTION/

    • 捕捉组,如果想要保留表达式中的一部分匹配信息,能够在 SUBSTITUTION 中应用 \1、\2 来示意其中的捕捉到的信息
  • 正则表达式的一些用法

    • . 除空格之外的”任意单个字符”(这里对吗,没有空格吗?)
    • * 匹配后面字符零次或屡次
    • + 匹配后面字符一次或屡次
    • [abc] 匹配 ab 和 c 中的任意一个
    • (RX1|RX2) 任何可能匹配 RX1 或 RX2 的后果
    • ^ 行首
    • $ 行尾
  • 正则表达式默认是贪心匹配的,能够在 *+ 后增加 ? 来变为非贪心的模式
  • 测试正则表白是否正确:debug
  • 匹配任意一个单词([^]+ 会匹配任意非空且不蕴含空格的序列)

    • 其中 ^ 如果放在表达式最开始,代表从行首开始匹配;否则含意为“不蕴含”
  • 对输出数据排序:sort

    • sort -n 会依照数字程序对输出进行排序(默认状况下是依照字典序排序 -k1,1 则示意“仅基于以空格宰割的第一列进行排序”。,n 局部示意“仅排序到第 n 个局部”,默认状况是到行尾。
    • sort -r 能够倒序
  • 把间断呈现的行折叠为一行并应用呈现次数作为前缀:uniq -c
ssh myserver journalctl # 读取日志
 | grep sshd
 | grep "Disconnected from"
 | sed -E 's/.*Disconnected from (invalid |authenticating)?user (.*) [^]+ port [0-9]+(\[preauth\])?$/\2/' # 获取用户名
 | sort | uniq -c # 将用户名排序并合并
 | sort -nk1,1 | tail -n10
 | awk '{print $2}' 
 | paste -sd, # 合并行,应用, 分隔
  • awk:是一种编程语言,十分长于解决文本

    • $0 示意整行的内容,$1$n 为一行中的 n 个区域,区域的宰割基于 awk 的域分隔符(默认是空格,能够通过 -F来批改)。
    • 所有以c 结尾,以 e 结尾,并且仅尝试过一次登陆的用户。| awk '$1 == 1 && $2 ~ /^c[^]*e$/ {print $2}' | wc -l

      • 该匹配要求文本的第一局部须要等于 1(这部分刚好是 uniq - c 失去的计数值)
      • 第二局部必须满足给定的一个正则表达式
BEGIN {rows = 0}
$1 == 1 && $2 ~ /^c[^]*e$/ {rows += $1}
END {print rows}
  • 命令行计算器,bc

    • bc -l 应用计算库,包含正弦余弦

课后练习

  1. 学习一下这篇简短的 交互式正则表达式教程.

     - \d 匹配数字,\D 匹配非数字的字符
     - . 能够匹配任意字符,\. 匹配句号
     - 匹配特定的字符,[abc],能够匹配 a 或 b 或 c
     - 去除特定字符,[^abc],能够匹配除了 a 或 b 或 c 的任意字符
     - 示意字符,\w 成果 = [A-Za-z0-9_],\W,非这些字符
     - 捕捉呈现肯定次数的字符
         - a{3},呈现 3 次
         - a{1,3},呈现不少于 1 次,不多于 3 次
     - * 匹配呈现任意次,+ 匹配呈现至多 1 次
     - ? 匹配是可选的,能够不呈现或呈现 1 次
     - 各种空格的解决:\s 能够匹配包含 space 空格,tab(\t),newline (\n),和回车(\r),十分有用。\S 匹配非空格的字符
     - ^ 匹配句首
     - $ 匹配句尾
     - 捕捉组
         - 正则表达式能够用于提取信息,用于进一步的解决
         - 应用 () 括起来,能够对失去的后果分组
         - 嵌套组:多个括号嵌套起来
     - 条件表达式,联合 () 和 |
     - 援用(back reference)- \0 残缺匹配 到的文本
         - \1 第一个组
         - \2 第二个组
  2. 统计 words 文件 (/usr/share/dict/words) 中蕴含至多三个 a 且不以's 结尾的单词个数。这些单词中,呈现频率前三的开端两个字母是什么?sed 的 y命令,或者 tr 程序兴许能够帮你解决大小写的问题。共存在多少种词尾两字母组合?还有一个很有挑战性的问题:哪个组合从未呈现过?(这里应用捕捉组是个更好的解法:.*(..),其中 \1 就能够捕捉到最初两个字母)

    # 统计词数
    cat /usr/share/dict/words | rg "\w*a\w*a\w*a\w*[^'s]"| tr"[:upper:]""[:lower:]" | uniq -c | wc -l
    # 5345
    
    #!/bin/bash
    words="./words.txt"
    cat /usr/share/dict/words | rg "\w*a\w*a\w*a\w*[^'s]"| tr"[:upper:]""[:lower:]" >words.txt
    
    run() {for i in {a..z}; do
            for j in {a..z}; do
                echo -n "$i$j"
                rg ".*$i$j$" $words | wc -l | awk '{print $1}'
            done
        done
    }
    
    run >occurance.txt
    
    echo "the most frenquent 3 combinations"
    cat occurance.txt | sort -nk2,2 -r | head -n3
    
    echo -n "there are total"
    cat occurance.txt | awk ' BEGIN {num = 0}
    $2 ~ "0" {num += 1}
    END {printf num} 'echo" combinations"echo"never appeared combinations"cat occurance.txt | awk' {if ($2 == "0") print $1} ' >nevershowed.txt
    paste -s -d , nevershowed.txt
  3. 进行原地替换听下来很有诱惑力,例如:sed s/REGEX/SUBSTITUTION/ input.txt > input.txt。然而这并不是一个理智的做法,为什么呢?还是说只有 sed是这样的? 查看 man sed 来实现这个问题
  4. 找出您最近十次开机的开机工夫平均数、中位数和最长工夫。在 Linux 上须要用到 journalctl,而在 macOS 上应用 log show。找到每次起到开始和完结时的工夫戳。在 Linux 上相似这样操作:

    Logs begin at ...

    systemd[577]: Startup finished in ...

    在 macOS 上, 查找:

    === system boot:

    Previous shutdown cause: 5

  5. 查看之前三次重启启动信息中不同的局部 (参见 journalctlb 选项)。将这一工作分为几个步骤,首先获取之前三次启动的启动日志,兴许获取启动日志的命令就有适合的选项能够帮忙您提取前三次启动的日志,亦或者您能够应用 sed '0,/STRING/d' 来删除STRING 匹配到的字符串后面的全部内容。而后,过滤掉每次都不雷同的局部,例如工夫戳。下一步,重复记录输出行并对其计数(能够应用uniq )。最初,删除所有呈现过 3 次的内容(因为这些内容上三次启动日志中的重复部分)。
  6. 在网上找一个相似 这个 或者这个的数据集。或者从这里找一些。应用 curl 获取数据集并提取其中两列数据,如果您想要获取的是 HTML 数据,那么 [pup](https://github.com/EricChiang/pup) 可能会更有帮忙。对于 JSON 类型的数据,能够试试[jq](https://stedolan.github.io/jq/)。请应用一条指令来找出其中一列的最大值和最小值,用另外一条指令计算两列之间差的总和。
退出移动版