Linux shell基礎2

junwind 發表於 2021-03-08
三大文字處理工具 grep , sed, awk

sed:
    行編輯器,逐行處理文字
    將文字內容逐行讀進模式空間(記憶體空間),匹配模式,進行處理 ,處理完成,顯示到螢幕
    預設情況下對原始檔內容不做修改,僅對模式空間中的內容做處理;處理完成後,將模式空間的內容列印到螢幕

    sed [options] 'addressCmd修飾符' file...
        -n    靜默模式,不再預設顯示模式空間中的內容
        -i    直接修改了原檔案
        -e script -e script      可以同時執行多個處理指令碼
        -f /path/to/sed_script : 指令碼檔案中每行一個處理指令碼,-f 讀取這個檔案
            sed -f /path/to/script  file
        -r : 選項,表示使用擴充套件正規表示式

        Address:指定要處理的地址行範圍
            Address:指定要處理的地址行範圍
            1,起始行,結束行 ; 如:1,100
                $:最後一行
                $-1:倒數第二行  ???

            2. /RegExp/   使用正則指定的模式
                如,以root開頭的行,/^root/

            3. /pattern1/,/pattern2/
                第一次被pattern1模式匹配到的行開始,至第一次被pattern2模式匹配到的行結束;這中間的所有行;

            4. 只給一個數值,精確到某行  lineNumber

            5. startline,+N  從起始行開始,向後的N行;一共是N+1行

        Command:
            d:刪除符合條件的行;
                sed '1,2d' /etc/fstab
                sed '3,$d' /etc/fstab
                sed '/oot/d' /etc/fstab   使用模式匹配來過濾特定的行
                sed '1,+2d' /etc/fstab    刪除123行
                sed '1d' /etc/fstab
                sed '/^\//d' /etc/fstab   刪除以斜線開頭的行

            p:顯示符合條件的行
                sed '/^\//p' /etc/fstab 
                    /dev/VolGroup00/LogVol00 /                       ext3    defaults        1 1
                    /dev/VolGroup00/LogVol00 /                       ext3    defaults        1 1
                    LABEL=/boot             /boot                   ext3    defaults        1 2
                    tmpfs                   /dev/shm                tmpfs   defaults        0 0
                    devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
                    sysfs                   /sys                    sysfs   defaults        0 0
                    proc                    /proc                   proc    defaults        0 0
                    /dev/VolGroup00/LogVol01 swap                    swap    defaults        0 0
                    /dev/VolGroup00/LogVol01 swap                    swap    defaults        0 0
                    發現符合條件的顯示了兩次,不符合的也顯示了一次?
                     注意:sed命令預設顯示模式空間一次,p處理後顯示一次
                    只顯示符合條件的行  sed -n '/^\//p' /etc/fstab 

            a \string : 在指定的行後面,追加新行,內容為"string";字串中間有空格的話,用引號引起來
                sed '/^\//a \# hello world' /etc/fstab 

                sed '/^\//a \# hello world\n# hello linux' /etc/fstab 

                \n : 可用於換行

            i \string :在指定的行前面新增新行,內容為string

            r 檔案路徑 : 將指定的檔案的內容,新增至符合條件的行處
                sed '2r /etc/issue' /etc/fstab 
                sed '$r /etc/issue' /etc/fstab

                在多行後面都新增
                sed '1,2r /etc/issue' /etc/fstab

            w 檔案路徑:將指定範圍內的內容,另存為至指定的檔案中;
                sed '/oot/w /tmp/oot.txt' /etc/fstab 
                sed -n '/oot/w /tmp/oot.txt' /etc/fstab 

            s/pattern/string/ :查詢並替換
                注意:sed逐行處理,預設列印模式空間內容
                逐行匹配pattern,將匹配到內容替換為string

                sed '1,$s/oot/OOT/' /etc/fstab 
                注意:1,$ 第一行到最後一行,不寫也能表示   sed 's/oot/OOT/' /etc/fstab

                把行首的斜線替換為#
                sed 's/^\//#/' /etc/fstab
                sed 's/\//#/' /etc/fstab 

                注意:預設只替換每行中,第一次被模式匹配到的字串
                如果想都替換,加修飾符:
                    g:全域性替換
                        s/pattern/string/修飾符
                            sed 's/\//#/g' /etc/fstab

                    i : 查詢時,忽略字元大小寫
                    s///  s###  [email protected]@@
                    sed '[email protected]/@#@g' /etc/fstab   這樣查詢反斜線就不用轉義了


後向引用:
    l..e --- l..er
        like---liker
        love---lover

    [[email protected] tmp]# cat sed.txt 
        hello,like
        hi, my love

    & : 引用模式匹配到的整個字串

    [[email protected] tmp]# sed 's#l..e#&r#g' sed.txt 
        hello,liker
        hi, my lover

    \(\)     \1  \2

    [[email protected] tmp]# sed 's#\(l..e\)#\1r#g' sed.txt 
        hello,liker
        hi, my lover

    有些時候,必須使用後向引用,如下:
        只引用匹配到的字串部分
        like---Like
        love---Love
        [[email protected] tmp]# sed 's#l\(..e\)#L\1#g' sed.txt 
            hello,Like
            hi, my Love

    history | sed 's#^[[:space:]]*##g' | cut -d' ' -f1

問題:給定一個路徑,取出父目錄?


sed練習:
1、刪除/etc/grub.conf檔案中行首的空白符;    sed '[email protected]^[[:space:]]@@' /etc/grub.conf
  sed -r '[email protected]^[[:spapce:]][email protected]@g' /etc/grub.conf

2、替換/etc/inittab檔案中"id:3:initdefault:"一行中的數字為5;
  sed '[email protected]\(id:\)[0-9]\(:initdefault:\)@\15\[email protected]' /etc/inittab

3、刪除/etc/inittab檔案中的空白行;
  sed '/^$/d' /etc/inittab

4、刪除/etc/inittab檔案中開頭的#號; 
  sed '[email protected]^#@@g' /etc/inittab

5、刪除某檔案中開頭的#號及後面的空白字元,但要求#號後面必須有空白字元;
  sed -r '[email protected]^#[[:space:]][email protected]@g' /etc/inittab

6、刪除某檔案中以空白字元後面跟#類的行中的開頭的空白字元及#
  sed -r '[email protected]^[[:space:]]+#@@g' /etc/inittab

7、取出一個檔案路徑的目錄名稱;
  echo "/etc/rc.d/" | sed -r '[email protected]^(/.*/)[^/]+/[email protected]\[email protected]'    
  基名:
  echo "/etc/rc.d/" | sed -r '[email protected]^/.*/([^/]+)/[email protected]\[email protected]'    

#abc
# hello world
   # hi world


練習:寫一個指令碼
1. 傳遞一個使用者名稱引數給指令碼,判斷此使用者的使用者名稱跟其基本組的組名是否一致,並將結果顯示出來?
#!/bin/bash
#
if [ `id -u -n $1` == `id -g -n $1` ]; then
    echo "to same."
else
    echo "No same."
fi
---------------------
#!/bin/bash
#
if [ $# -lt 1 ]; then
    echo "Usage: 8.sh ARG"
    exit 9
fi

if ! id $1 &> /dev/null; then
    echo 'No such user.'
    exit 10
fi

if [ $1 == `id -gn $1` ]; then
    echo "yiyang"
else
    echo "buyiyang"
fi

2. 傳遞三個引數給指令碼,第一個為整數,第二個為算術運算子,第三個為整數,將計算結果顯示出來,
要求保留兩位精度,形如:./calc.sh 5 / 2
bc
echo "scale=2;111/22;" | bc
[[email protected] tmp]# bc <<< "scale=2;111/22"
5.04




3. 傳遞3個引數給指令碼,引數均為使用者名稱,將此些使用者的賬號資訊提取出來後,放置於 /tmp/testusers.txt檔案中,
並要求每一行行首有行號;
echo "1 $line" >> /tmp/testusers
echo "2 $line" >> /tmp/testusers



4. 寫一個指令碼,
判斷當前主機的cpu生產商,其資訊在/proc/cpuinfo檔案中 vendor id 一行中,
如果其生產商為AuthenticAMD,就顯示其為AMD公司;
如果其生產商為GenuineIntel,就顯示其為Intel公司;
否則,就說其為非主流公司;



5. 寫一個指令碼,
給指令碼傳遞三個整數,判斷其中的最大數 和 最小數,並顯示出來;
多個數值比較:氣泡排序,演算法
MAX=0
MAX -lt $1
    MAX=$1
MAX -lt $2
    MAX=$2
...


本作品採用《CC 協議》,轉載必須註明作者和本文連結
六月的風