Linux SHELL

  • You do not have permissions to view this page - please try logging in.

版本為 07:02, 28 Jul 2026

到這個版本。

返回到 版本存檔.

查閱目前版本

標題索引

 

快速備份設定檔

cp config.txt{,.bak}

天氣氣象

curl http://v2.wttr.in/taoyuan
curl http://wttr.in/taoyuan

numfmt 數字顯示格式化

$ numfmt --grouping 123456789
123,456,789

$ numfmt --from=si 2M
2000000
$ numfmt --from=iec 2M
2097152 

$ numfmt --from=iec-i 2Gi  
2147483648

$ numfmt --to=iec 1000000 
977K

tr 指令

去除檔案內的單引號

tr -d \'

建立暫存檔的方法

TMPFILE=$(mktemp) || exit 1
echo "Our temp file is $TMPFILE"
# specify the directory
TMPFILE=$(mktemp -p /path/to/tmpdir)
echo "Our temp file is $TMPFILE"
#!/bin/bash
# Deleting the File After Script Exit
trap 'rm -f "$TMPFILE"' EXIT
TMPFILE=$(mktemp)|| exit 1
echo "Our temp file is $TMPFILE"
// 建立臨時檔案或目錄
TMPFILE=$(mktmp)
TMPDIR=$(mktmp -d)
這分別會在 /tmp 目錄建立以亂數取名的臨時檔案或臨時目錄,記得程式最後要將這些臨時檔案目錄移除

監看一個文字檔內容是否有變動

cat $1 > /tmp/$1.tmp
while(true)
do
    if [[ $(diff $1 /tmp/$1.tmp) ]]
        then
            $2
            cat $1 > /tmp/$1.tmp
    fi
    sleep 2
done

Usage: watchdog.sh log.txt "echo hello"

有人登入到 root 時自動發通知郵件

編輯 /root/.bashrc,加上這一行

echo "ALERT – Root Shell Accessed by `whoami` Login on:" `date` | mail -s "Alert: User `whoami` logged on to `hostname`" user@your.company.com

SHELL 管理

// 查出目前使用哪種 SHELL

#> ps -p $$
#> echo $0
#> echo $SHELL 

// 執行 SHELL 的方式

#> sh file
#> . file
#> source file

// 在 SHELL 內執行另一個外部 SHELL 或指令
使用 pipe line

echo"md5sum $X > $X.sum "| bash

使用 eval

get_arch="uname -p"
if [ "`eval "$get_arch"`" = "i686" ]; then
....
fi 

// 命令模式提示字元的路徑名稱太長
加上這變數

PROMPT_DIRTRIM=2

批次修改密碼

usernames=$(cat /etc/passwd  | grep bash | sed 's/:.*//g)
for user in $usernames; do 
    echo "somepassword" | passwd --stdin $user
done

有些版本不支援 --stdin,可以改用

usernames=$(cat /etc/passwd  | grep bash | sed 's/:.*//g)
for user in $usernames; do 
    echo "$user:somepassword" | chpasswd
done

建立隨機密碼

cat /dev/urandom | tr -c -d '[:alnum:]' | head -c 16;echo

多個 pipeline 指令

command1 | command2 | commandN

OR

command1 | filter_data_command > output

OR

get_data_command | verify_data_command | process_data_command | format_data_command > output.data.file

取得每個指令的回應碼

// 輸出每個指令的回應碼,以 Array 方式
echo "${PIPESTATUS[@]}"

// 輸入第一個與第二個指令的回應碼
echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"

Command Line 快捷鍵操作

 鍵盤 說明
 Ctrl + a 游標快速移到做前端
 Ctrl + e 游標快速移到最末端
 Alt + f 游標往前移動一段文字
 Alt + b 游標往後移動一段文字
 Ctrl + d 刪除目前游標上的一個字元
 Alt + d 刪除目前游標上的一段文字
 Ctrl + n 下一個歷史指令
 Ctrl + p 上一個歷史指令
 Ctrl + u 裁掉目前游標之前的文字
 Ctrl + k 裁掉目前游標之後的文字

column 指令

格式化輸出

# (printf "DeviceName On MountPoint Type FileSystem\n";mount) | column -t     
DeviceName                      On  MountPoint                Type  FileSystem
/dev/mapper/vg_homepbx-lv_root  on  /                         type  ext4         (rw)
proc                            on  /proc                     type  proc         (rw)
sysfs                           on  /sys                      type  sysfs        (rw)
devpts                          on  /dev/pts                  type  devpts       (rw,gid=5,mode=620)
tmpfs                           on  /dev/shm                  type  tmpfs        (rw)
/dev/sda1                       on  /boot                     type  ext4         (rw)
none                            on  /proc/sys/fs/binfmt_misc  type  binfmt_misc  (rw)

install 指令

快速建立一個目錄且設定好 owner/group,存取權限。

/usr/bin/install -o www-data -g www-data -m 0755 -d /var/log/freegeoip

系統資訊 /proc

CPU:

cat /proc/cpuinfo

Memory:

cat /proc/meminfo

OS Version:

cat /proc/version

陣列 Array

  • 陣列長度:${#str_list[@]}
  • 陣列內容:${str_list[@]}
#!/bin/bash
str_list=("aaa" "bbb" "ccc" "ddd")
echo ${#str_list[@]}
for i in ${str_list[@]}
do
  echo "$i"
done
# Script to split a string based on the delimiter
my_string="Ubuntu;Linux Mint;Debian;Arch;Fedora"
IFS=';' read -ra my_array <<< "$my_string"

#Print the split string
for i in "${my_array[@]}"
do
    echo $i
done
# Script to split a string based on the delimiter
my_string="Ubuntu;Linux Mint;Debian;Arch;Fedora"  
my_array=($(echo $my_string | tr ";" "\n"))

#Print the split string
for i in "${my_array[@]}"
do
    echo $i
done

mail 指令

指定 sender name)
使用 Mutt,適用 CentOS 4

$ export EMAIL="No Reply<noreply@my.com>"
$ echo "mail body" | mutt -s "Test Mail" touser@my.com

使用 mailx,適用 AIX 5.3

$ echo "mail body" | mailx -s "Test mail" -r noreply@my.com touser@my.com

從外部的 SMTP server 轉信)
使用 mailx 指令

// 安裝 mailx
yum install mailx

// 寄信
$ echo "This is the message body and contains the message" | mailx -v \
> -r "someone@example.com" \
> -s "This is the subject" \
> -S smtp="mail.example.com:587" \
> -S smtp-use-starttls \
> -S smtp-auth=login \
> -S smtp-auth-user="someone@example.com" \
> -S smtp-auth-password="abc123" \
> -S ssl-verify=ignore \
> yourfriend@gmail.com 

TIPs:

-v 會顯示完整連線訊息,內容類似如下

Resolving host smtp.gmail.com . . . done.
Connecting to 74.125.68.109:587 . . . connected.
220 mx.google.com ESMTP je4sm32812877pbd.94 - gsmtp
>>> EHLO enlightened
250-mx.google.com at your service, [122.163.43.21]
250-SIZE 35882577
250-8BITMIME
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING

迴圈 loop 開發技巧

// for loop 的應用
$> for i in var1 var2 var3; do echo $i; done
$> for ((i=1;i<=10;i++)); do echo $i; done
$> for i in $(ls *.log); do echo $i; done  

$> for t in {1..10};do  echo $t; done
1
2
3
4
5
6
7
8
9
10

$> for t in {1..10..2};do  echo $t; done
1
3
5
7
9

## 列出目前資料夾的所有目錄名稱
$> for dir in */;do echo "${dir%/}"; done

## 讀取檔案內容
$> cat tables_name.lst | while read sch tab;do
> echo "export to $tab.ixf of ixf messages export_$tab.msg select * from $sch.$tab"
> done

// while loop 的應用
// 每 3 秒監看 /worktmp 的磁碟使用狀況
$> while true;do
> df -h | grep /worktmp
> sleep 3
> done

// 管理 DB2 時常用
$> while read s t;do
> db2 "select count(*) from $s.$t"
> done < tables.lst > count-tables.out

如果是 CSV
$> while IFS=, read s t;do
> db2 "select count(*) from $s.$t"
> done < tables.csv > count-tables.out

// 大量刪除名稱包含有 /plugins/mactrack 的程式 
$> ps -ef | grep "/plugins/mactrack" | awk '{system("kill " $2);}'

// 迴圈計數 Loop Counter
x=1
while [ $x -le 5 ]
do
  echo "Welcome $x times"
  x=$(( $x + 1 )) 或者 x=$[$x + 1]
done

sort 指令

sort -t ',' -k5,5 -k1,1 -k9,9 -k3,3 -k11,11 my.csv
  •  -t 分隔符號
  • -k5,5 排序第 5 欄,以字串類型排列
  • 欄位排序先後依序為第 5, 1, 9, 3, 11 欄
  • 欄位排序若要以數值方式來排,改成 -k5,5n

刪除 * 天前的舊備份檔

reference to undefined name 'syntax' Exception of type 'MindTouch.Deki.Script.Runtime.DekiScriptUndefinedNameException' was thrown. (click for details)

date 指令

SHELL 寫法

NOW=`date "+%Y/%m/%d %H:%M:%S"`

eval `date "+day=%d; month=%m; year=%Y"`
BKNAME="cacti-backup-$year-$month-$day.tar.gz"
NOWD=$(date +"F")   # YYYY-MM-DD
NOWT=$(date +"%T")  # H:M:S

%T     time; same as %H:%M:%S

將 Date 轉換為 EPOCH 時間格式
用 perl 可用於 AIX

perl -e 'use Time::Local; print timelocal(0,25,1,11,11,2008), "\n";'

常用幾種格式

# echo `date "+%y-%m-%d_%H%M%S"`
17-05-22_105503

# echo `date "+%Y/%m/%d"`
2015/07/17

# echo `date "+%F"`
2015-07-17

# date --date="49 days ago"
日  9月 11 16:17:02 CST 2016

# date --date="1 month ago"
五  9月 30 16:17:34 CST 2016

計算程式執行所花費的時間

start=`date "+%Y/%m/%d %H:%M:%S"`
start_s=$(date -d "$start" +%s)

Sleep 20

end=`date "+%Y/%m/%d %H:%M:%S"`
end_s=$(date -d "$end" +%s)
diff=$((end_s - start_s))

find 指令

// 找出大於 1000 MB 的檔案

find / -type f -size +1000M

// 搬移指定日期範圍的檔案
將修改日期是 2012 - 2014 的所有檔案搬移至 /export_data/2012-2014。

touch --date "2012-01-01" /tmp/start
touch --date "2015-01-01" /tmp/end

find /home/ams/ipdr -type f -newer /tmp/start -not -newer /tmp/end > 2012-2014.lst
find /home/ams/ipdr -type f -newer /tmp/start -not -newer /tmp/end -exec cp -a {}  /export_data/2012-2014 \;
find /home/ams/ipdr -type f -newer /tmp/start -not -newer /tmp/end -exec rm -f {} \;

// 列出 2018-03-20 至 2018-04-10 期間曾修改過的檔案

find ~/ -xdev -newermt 2018-03-20 \! -newermt 2018-04-10 -type f -ls

// 列出 365天以前/20分鐘以前 的所有檔案

find ./ -ctime +365 -ls
find ./ -cmin +20 -ls

TIP:

ctime 檔案建立時間

mtime 最近檔案修改時間

atime 最近存取檔案時間

// 找尋3日內曾異動過的檔案,並轉換 Excel format(csv)

find . -xdev -mtime -3 -ls > found.list
sed 's/^[ ]*//g;s/[ ][ ]*/   /g' found.list | awk '{print $3","$5","$6","$7","$8" "$9","$10","$11}' > found.list.csv

// 列出剛剛異動過的檔案

最近 5 分鐘異動過的檔案(包含權限與新增檔案)
find dir -cmin -5

最近 10 分鐘修改過的檔案
find dir -mmin 10

// 目錄 data 內有許多以日期命名的小 log,需要將去年的所有 log 搬到新目錄 archive-2013
註:排除目錄 ./archive-2013

cd data/
mkdir archive-2013
find ./ -path "./archive-2013" -prune -o -name "dcdb_13*" -exec mv {} archive-2013 \;

TIPs:

要排除多個目錄時可以改成
find ./  \( -path "./dir1" -o -path "./dir2" \) -prune -o -name "dcdb_13*" -exec mv {} archive-XXXX \;

// 列出最大檔案的清單

find . -type f -exec wc -c {} \; | sort -nr | head 

// 檔案搜尋結果按時間先後作排序

find /istrpt/arlog/ -name "*.LOG" -print | xargs ls -lt

計算指定目錄底下的檔案總數量

用 find

計算目前目錄底下所有檔案數
find . -type f | wc -l 

計算第一層所有子目錄的檔案數並排序清單
find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo $(find {} -type f | wc -l) {}' | sort -n
NOTE: 第一層子目錄名稱不可包含空格 

用 rsync 方式計算 /usr 底下檔案數

rsync --stats --dry-run -ax /usr /tmp

Number of files: 326,373 (reg: 211,698, dir: 24,284, link: 90,391)
Number of created files: 326,373 (reg: 211,698, dir: 24,284, link: 90,391)
Number of deleted files: 0
Number of regular files transferred: 211,698
Total file size: 7,180,685,730 bytes
Total transferred file size: 7,178,524,818 bytes

NOTE: 這指令實際不會作檔案複製,/tmp 只是一個假目錄,回傳結果是 reg: 211698 就是檔案總數

用 tree

tree /mydir -a | tail -n 1

5 directories, 56 files

NOTE: 當目錄底下有包含 symbolic link 也會被計算

輸出多行的文字訊息

reference to undefined name 'syntax' Exception of type 'MindTouch.Deki.Script.Runtime.DekiScriptUndefinedNameException' was thrown. (click for details)

一次建立或列出多個指定的目錄

mkdir {AAA,BBB,CCC}

grep 指令

更多教學:

// 字串過濾搜尋

使用 . (period) 表示一個任意字元
$ grep dev.sda /etc/fstab
/dev/sda3       /               reiserfs        noatime,ro 1 1
/dev/sda1       /boot           reiserfs        noauto,noatime,notail 1 2
/dev/sda2       swap            swap            sw 0 0
#/dev/sda4      /mnt/extra      reiserfs        noatime,rw 1 1

使用 [ ]
$ grep dev.sda[12] /etc/fstab
/dev/sda1       /boot           reiserfs        noauto,noatime,notail 1 2
/dev/sda2       swap            swap            sw 0 0 

使用 [^12] 表示非1,2字元
$ grep dev.sda[^12] /etc/fstab
/dev/sda3       /               reiserfs        noatime,ro 1 1
#/dev/sda4      /mnt/extra      reiserfs        noatime,rw 1 1

使用正規表示
$ grep '^#' /etc/fstab
# /etc/fstab: static file system information.
#
$ grep '^#.*\.$' /etc/fstab
# /etc/fstab: static file system information.
#
$ grep 'foo$' filename

搜尋與關鍵字大小寫一致的行
grep -w "boo" myfile.txt

搜尋包含特殊字元 *** 的關鍵字
grep '\*\*\*' myfile.txt

搜尋 email 地址
grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" /path/to/data

搜尋 IP 位址
egrep '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' /etc/hosts

更多應用語法
grep '[vV][iI][Vv][Ee][kK]' filename
grep '[vV]ivek' filename
grep -w '[vV]ivek[0-9]' filename
grep 'foo[0-9][0-9]' filename
grep '[A-Za-z]' filename
grep [wn] filename
  

// 搜尋多個關鍵字(使用正規運算式)

> ls /var/log/ | grep -E "http|secure"
或
> ls /var/log/ | grep "http\|secure" 

// 檢查設定檔的參數

reference to undefined name 'syntax' Exception of type 'MindTouch.Deki.Script.Runtime.DekiScriptUndefinedNameException' was thrown. (click for details)

// 在許多檔案內尋找特定字串內容
應用:程式碼編寫及除錯

cd /var/www/html
grep -r "[搜尋關鍵字]" *

grep -Ril "specific_text" /path/to/dir 

// 搜尋特定字串的文字段落內容
應用:檢查系統的硬體裝置,以及類似 AIX 的 grep -p

# lspci -v | awk '/ATI/,/^$/'
01:03.0 VGA compatible controller: ATI Technologies Inc Rage XL (rev 27) (prog-if 00 [VGA])
        Subsystem: Compaq Computer Corporation: Unknown device 001e
        Flags: bus master, stepping, medium devsel, latency 64
        Memory at fc000000 (32-bit, non-prefetchable) [size=16M]
        I/O ports at 3000 [size=256]
        Memory at fbff0000 (32-bit, non-prefetchable) [size=4K]
        Capabilities: [5c] Power Management version 2

檔案:grepp.awk
使用方法:

#> lspci -v | grepp.awk ATI

列出目錄內最新的 5 個檔案

Sample#1:

find . -not -type d -printf "%T+ %p\n" | sort -r | awk '{print $2}' | head -n 5
./b01.tar.gz
./b02.tar.gz
./b03.tar.gz
./b04.tar.gz
./b05.tar.gz

Sample#2:

find . -name "*" -type f | xargs ls -lt | head -n 5 | awk '{print $9}'
./b11.tar.gz
./b10.tar.gz
./b09.tar.gz
./b08.tar.gz
./b07.tar.gz

依照檔案大小排序

# 從小到大
ls -l -Sr1 /path-to-dir

# 從大到小 
ls --sort=size /path-to-dir

# 排序後清單,逐一做壓縮
ls -Sr1 worktmp/ | while IFS=$'\n' read -r file; do gzip -v9 "$file"; done

# 列出前十大的檔案清單
du -csk * | sort -rn | head -10

大小寫的轉換

#轉換成小寫
toLower() {
   echo $1 | tr "[:upper:]" "[:lower:]"
 } 

#轉換成大寫
ToUpper() {
   echo $1 | tr "[:lower:]" "[:upper:]"
 }

檢查 MySQL DB 是否存在

# Checking if DB XXX existed
# if existed, return 0
mysql -uroot -p$DBPASS --batch --skip-column-names -e "SHOW DATABASES LIKE '$DBNAME';" | grep $DBNAME > /dev/null; echo $?

test 指令

(1) 字串或文字的比對

Str1 == str2 | 當str1與str2相同時, 傳回True
Str1 != str2| 當str1與str2不同時, 傳回True
Str1 < Str2 
Str1 <= Str2
Str1 > Str2
Str1 >= Str2
Str      | 當str不是空字符時, 傳回True
   -n str    | 當str的長度大於0時, 傳回True
   -z str    | 當str的長度是0時, 傳回True

(2) 數字(整數) 比對

Int1 -eq int2 |當int1等於int2時, 傳回True
Int1 -ge int2 |當int1大於/等於int2時, 傳回True
Int1 -le int2 |當int1小於/等於int2時, 傳回True
Int1 -gt int2 |當int1大於int2時, 傳回True
Int1 -ne int2 |當int1不等於int2時, 傳回True
Int1 -lt int2 |當int1小於 int2時, 傳回True 

More Sample Codes:

reference to undefined name 'syntax' Exception of type 'MindTouch.Deki.Script.Runtime.DekiScriptUndefinedNameException' was thrown. (click for details)

(3) 檔案的比對

-e file   | 檔案是否存在
-d file   | 當file是一個目錄時, 傳回 True
-f file   | 當file是一個普通檔案時, 傳回 True
-r file   | 當file是一個可讀檔案時, 傳回 True
-s file   | 當file檔案長度大於0時, 傳回 True
-w file   | 當file是一個可寫檔案時, 傳回 True
-x file   | 當file是一個可執行檔案時, 傳回 True

(4) shell的邏輯操作符用於修飾/連接包含整數,字符串,文件操作符的表達式

! expr        |當expr的值是False時, 傳回True

更多範例

reference to undefined name 'syntax' Exception of type 'MindTouch.Deki.Script.Runtime.DekiScriptUndefinedNameException' was thrown. (click for details)

特殊變數及進階應用

變數 說明
 $0  腳本檔名
 $1  第1個參數
 $2  第2個參數
 ${10}  第10個參數 #10
 $#  參數的個數
 $*  顯示所有參數 (作為一個字串)
 $@  顯示所有參數 (每個為一個獨立字串)
 ${$*}  傳遞到腳本中的參數的個數
 ${$@}  傳遞到腳本中的參數的個數
 $?  腳本結束後的傳回值
 $$  腳本的程序 ID
 $_  前個命令的最後一個參數
 $!  最後一個執行程序的 ID
u=${1:-root}  如果 $1 未指定,就賦予值 root
u=${USER:foo}  如果 $USER 未指定,就賦予值 foo;無法用於 $1, $2 變數
len=${#var}  計算 $var 字串的長度

 

如果 $2 未指定或空值,輸出錯誤訊息

${varName?Error varName is not defined}
${varName:?Error varName is not defined or is empty}

MESSAGE="Usage: mkjail.sh domain-name"  ## define error message
_domain=${2:?"Error: ${MESSAGE}"}              ## you can use $MESSAGE too

${varable} 進階用法

https://linuxconfig.org/introduction...ter-expansions

 

將執行後的所有輸出訊息導入一個檔案

reference to undefined name 'syntax' Exception of type 'MindTouch.Deki.Script.Runtime.DekiScriptUndefinedNameException' was thrown. (click for details)
TIPs
不適用在內容裡有 python 指令的訊息輸入,輸入等待的畫面會無法顯示。
reference to undefined name 'syntax' Exception of type 'MindTouch.Deki.Script.Runtime.DekiScriptUndefinedNameException' was thrown. (click for details)

格式化輸出訊息

  • %s 字串
  • %d 整數
printf "%-40s ..................%s\n" "Disable the service $1" "[$2]"
Disable the service apmd                 ..................[OK]
Disable the service bluetooth            ..................[OK]
Disable the service hidd                 ..................[OK]
Disable the service cups                 ..................[OK]
Disable the service firstboot            ..................[OK]
Disable the service readahead_early      ..................[OK]
printf "%40s ..................%s\n" "Disable the service $1" "[$2]"
                Disable the service apmd ..................[OK]
           Disable the service bluetooth ..................[OK]
                Disable the service hidd ..................[OK]
                Disable the service cups ..................[OK]
           Disable the service firstboot ..................[OK]
     Disable the service readahead_early ..................[OK] 

數值簡單運算

日期運算

YEAR=$((YEAR-1))
MONTH=$((MONTH-1))
echo "($YEAR + ($YEAR/4) - ($YEAR/100))" 

X的Y次方

pow() {
    if [ -z "$1" ]; then
        echo "usage: pow <base> <exponent>"
    else
        echo "$1^$2" | bc
    fi
}

pow2() {
    if [ -z "$1" ]; then
        echo "usage: pow <base> <exponent>"
    else
        echo "$[$1**$2]"
    fi
}

pow 2 3

去除變數的開頭0

# $1 is month, $2 is day, $3 is year
# Strip off leading off zeros from month and day
MONTH=${1#0}
DAY=${2#0}
YEAR=$3

去除變數的末端字元 .XXX

NAME=${1%.*}
echo $NAME

更多範例

Operator "#" means "delete from the left, to the first case of what follows."
    $ x="This is my test string."
    $ echo ${x#* }

    is my test string.

Operator "##" means "delete from the left, to the last case of what follows."
    $ x="This is my test string."
    $ echo ${x##* }

    string.

Operator "%" means "delete from the right, to the first case of what follows."
    $ x="This is my test string."
    $ echo ${x% *}

    This is my test

Operator "%%" means "delete from the right, to the last case of what follows."
    $ x="This is my test string."
    $ echo ${x%% *}

    This

比對兩個檔案是否相同

cmp -s file1 file2
rc=$? 
  • rc=0:兩個一模一樣
  • rc=1:兩個不同檔案
  • rc>1:比對發生錯誤
     

取得檔案的容量

#!/bin/bash
FILENAME=/home/heiko/dummy/packages.txt
FILESIZE=$(stat -c%s "$FILENAME")
echo "Size of $FILENAME = $FILESIZE bytes."

取得指定檔案的絕對路徑

// 指定的檔案
readlink -f <file.name>

// 目前檔案
MY_PATH=$(readlink -f "$0") ;目前檔案的絕對路經
MY_PATH=$( cd $( dirname "$0" ) && pwd ) 

取得目前的檔案名稱

>echo $0
./test.sh

>echo `basename $0`
test.sh 

expr 指令

; 過濾郵件位址的使用者名稱
; 列出所有 fax 開頭網域的郵件位址的使用者名稱
expr "001123@fax.home.net" : '\(.*\)@fax*' 

註:

\(    \)  等於是 (  ),所包含的就是要輸出內容
.  任何字元
.*  不限字數的任何字元
[^=]  非 = 的字元

awk 指令

搜尋字串

awk '/^this/{print $0}'         ;與 sed -n '/^this/p' 相同

我們經常使用 sort 與 uniq 指令,從檔案中找出並移除重複項目。不過如果你不希望你的原始檔被排序或更動,這時正是 awk 派上用場的時候,我們可以用 awk 截取不重複記錄並儲存在新的檔案中:

awk '!x[$0]++' filewithdupes > newfile

搜尋含 disabled 的行,並列出第 1, 3 欄的內容

awk '/disabled/{print $1, $3}'

取值做計算

awk '{print "up " $1 /60 " minutes"}' /proc/uptime

df -lP -text4 |awk '{sum += $4} END {printf "%d GiB\n", sum/1048576}'
df -lP -text4 |awk '{sum += $4} END {printf "%d GiB\n", sum/2**20}'

加上判斷式

$> df -k |grep "/dev/" | awk '($2 > 0 && ((1 - $3/$2)  > 0.9) ) {print $0 }'

$> awk -F" " '{print ($7 != "A")?$0"***":$0}' myfile

搜尋每行的第9欄,如果不是 0x00000000 時就顯示該行訊息

$> cat info.out | awk '($9 != "0x00000000") {print}'

列出 uid >= 500 且 <= 10000 的行

$> export UGIDLIMIT=500
$> awk -v LIMIT=$UGIDLIMIT -F: '($3>=LIMIT) && ($3<=10000)' /etc/passwd

解決長整數顯示問題

$ awk  'BEGIN {print 12345678901234567890}'
1.23457e+19

方法一
$ awk  'BEGIN {printf("%d\n", 12345678901234567890)}'
12345678901234567168

方法二
$ awk  'BEGIN {OFMT="%.0f"; print 12345678901234567890}'
12345678901234567168 

列出 uid=0 的帳號

$> awk -F: '($3 == "0") {print}' /etc/passwd

列出最後一個欄位的值

ls -ltd */ | awk -F ' ' '{print $NF}'

格式化輸出

awk '{ printf("1-minute: %s\n5-minute: %s\n15-minute: \
 %s\n",$1,$2,$3); }' /proc/loadavg

計算目錄的檔案大小

reference to undefined name 'syntax' Exception of type 'MindTouch.Deki.Script.Runtime.DekiScriptUndefinedNameException' was thrown. (click for details)

sed 指令

; 列出第 100 行以下的所有文字
; 若要刪除,可將 p 換成 d。
sed -n '100,$p'  my.txt

; 列出第 3 行以上的所有文字
sed '3q' my.txt

; 列出第 130 行
sed -n '130{p;q}' my.txt

; 列出第 100 - 130 行文字
sed -n '100,130p' my.txt
sed -n '100,130p;130q' my.txt

; 列出關鍵字 all 以下所有行
sed -n '/all/,$p' my.txt

; 搜尋關鍵字,並列出這個段落的所有文字
sed -n '/keyword/,/^$/p'

; 列出關鍵字 Top 與 Bottom 之間的所有文字
sed -n '/Top/,/Bottom/p'

 ; 搜尋字串的那一行
sed -n "/PATTERN/p" my.txt

; 在第 2 行的上方,插入文字 xxx
sed '2i xxx' my.txt

; 在搜尋的行下方新增字串
sed -e '/patterm/ a\newstring' my.txt

; 在所有文字的行首加上 #
sed 's/^/# /' my.txt

; 在所有文字的行尾加上 End
sed 's/$/ End/' my.txt

;刪除行首為# 的行
sed '/^#/d' 

; 刪除行首為 # 或空白的行
sed '/^#\|^$/d'

;刪除多個關鍵字的行, ADMIN_ERP_ROLE, RPT01,...
sed '/ADMIN_ERP_ROLE/d;/RPT01/d'

;刪除空白行
sed '/^$/d'
sed '/^\s*$/d'

;移除行裡的空白與 Tab 字元
sed 's/^[ \t]*//'
sed 's/^[ \t]*//;s/[ \t]*$//'

;將每一行裡是兩個以上空白字元, 都換成一個 comma 符號
sed "s/  \+/,/g"

; 刪除空格
sed 's/[[:space:]]//g' mywords

; 刪除所有行尾的空格字元
sed -i 's/[[:space:]]*$//'

; 刪除行尾的 ^M (CR 字元)
sed 's/^M//g'      NOTE: to get ^M type CTRL+V followed by CTRL+M
sed 's/\r$//g'

; 刪除 iXXXX 的帳號, XXXX 是數字
sed '/^i[0-9]*/d' mypasswd

;執行多個規則
sed -e '/^#/d' -e '/^$/d' 

;快速取代字串
sed 's/old/new/' mywords
sed 's|old|new|' mywords

; 搜尋關鍵字 'astlogdir =>' 的這一行,取代行字串為 'astlogdir => /mnt/usb/asterisk_log'
; .*$ 表示行尾前的所有字串
sed -i 's/astlogdir =>.*$/astlogdir => \/mnt\/usb\/asterisk_log/g'

; 搜尋 'none',並且在該行行首加上 '#'
sed 's/none/#&/g' mywords 

; 在字串  'daemon' 的下方插入另一個檔案 3.txt 的內容
sed '/daemon/r 3.txt' mywords 

; 搜尋文字 'daemon',將符合的內容寫到檔案 3.txt
sed -n '/daemon/w 3.txt' 1.txt 

; 將符合文字 'root' 內容的下一行,插入特定的文字 'test test'
[root@linux-3 ~]# sed ‘/root/a test test’ 1.txt
root:x:0:0:root:/root:/bin/bash
test test
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 

; 將符合文字 'daemon' 內容的上一行,插入特定的文字 'test test'
[root@linux-3 ~]# sed '/^daemon/i test test' 1.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
test test
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

; 搜尋所有文字是 'ext3' 的,用 [ ] 框起來
sed 's/ext3\+/[&]/g' my.txt

; 搜尋文字並取代部份的內容
sed -i 's/^\(User\|Group\).*/\1 asterisk/' /etc/httpd/conf/httpd.conf

// 找出關鍵字的右側字串內容

$ cat cookie.txt
xxxx  FALSE   /       FALSE   0       PHPSESSID       dbbr5nsmib9tgm0h97sbq8ovd0

$ cat cookie.txt | sed 's/^.*PHPSESSID[ \t]*//' 
dbbr5nsmib9tgm0h97sbq8ovd0

// 找出行的左側內容

列出 10.14.25.196 與 GA016E38 (Hex IP)

 $ cat input.txt
 
 GA160223.MAE3.219594040120
10.14.25.196.49611.200203080358
GA016E38.O5FA.259D81215343
10.4.1.29.41266.200114031620
GA12640A.M6EE.20EDC3093010

$ sed 's/^\(.*\)\.[A-Z0-9]*\.[A-Z0-9]*/\1/' input.txt

GA160223
10.14.25.196
GA016E38
10.4.1.29
GA12640A

 

// 對 CSV 檔案的內容,將所有分隔符號 comma 置換成 @@,但必須排除有包含 comma 的文字敘述,這些文字內的 comma 前個字元會有個空白

sed 's/\(,\)\([^ ]\)/@@\2/g' orig.csv

TIPs:

s 搜尋

\( \) \( \) 用括弧區分兩個字元

[^ ] 非空白的字元

\2 第二個字元,這裡要配合括弧的用法

g 作全文置換,若沒有此參數,預設只會置換第一個符合的字元

// 搜尋 A.AA B.BB C.CC 3個數值,並以指定的格式輸出

reference to undefined name 'syntax' Exception of type 'MindTouch.Deki.Script.Runtime.DekiScriptUndefinedNameException' was thrown. (click for details)

TIPs:

^\([0-9]\+\.[0-9]\+\) \([0-9]\+\.[0-9]\+\) \([0-9]\+\.[0-9]\+\).*$  搜尋語法
1-minute: \1\n5-minute: \2\n15-minute: \3 輸出語法

// 取代所有的 mailbox = xxx 為 mailbox = xxx@context

sed 's/^mailbox = [0-9]*/&@context/g' users.conf

// 搜尋特定區段的 AllowOverride None
只取代這個區段所包含的關鍵字

<Directory "/var/www/html">
...

<Directory>

sed -i ':a;N;$!ba;s/AllowOverride None/AllowOverride All/2' /etc/httpd/conf/httpd.conf

// 擷取 { } 所包含的所有文字

<br/> <b>Notice</b>: Undefined variable: sn in <b>/var/www/raida/service/fix.php</b> on line <b>259</b><br/> {"server":"RAIDA17","sn":"","status":"success","message":"Fixed: Unit's AN was changed to the PAN. Update your AN to the new PAN.","time":"2017-04-08 06:08:25"}

echo $( cat http_get.txt ) | sed  's/.* \({.*}\)$/\1/'

// 擷取 [ ] 內的文字

echo "[1070059:1,1070060:1,1070039:1]" | sed  's/^\[\(.*\)\]$/\1/'

列出某個執行中的 process 會開啟的相關檔案列表

lsof -p `pidof <app_name>`

隱藏/消除文字檔內以#或;符號開頭的每一行

grep -Ev "^(#|;)" example.txt

延伸應用:
自動刪除文字檔內所記載的目錄及檔案,例如:

# file: remove.list
# please remove this directory and files below
/path/to/file.1
/path/to/file.2
/path/to/dir/
/path/to/dir-1/

依照檔案清單做連續刪除的指令行:

grep -Ev "^(#|;)" remove.list | xargs -n 1 ls -l
grep -Ev "^(#|;)" remove.list | xargs -n 1 rm -rf 

快速修改大量檔案的副檔名

## *.old -> *.new
for fname in $(ls *.old);do echo "mv $fname ->"; echo $(echo $fname |sed 's/.old/.new/');mv $fname $(echo $fname | sed 's/.old/.new/');done

如何取得 process ID

for SHELL process:

#!/bin/bash
#
/path/to/my/shell.sh &
echo $PPID
# pidof <app_name>
#!/bin/bash
echo $$ 

for java process:

#!/bin/bash
#
/path/to/java myjava.jar &
echo $!

取得目前 IP address

internip=`ifconfig | grep -m 2 ^ | cut -f 2 -d ":" | cut -f 1 -d " " | tail -1`
privnet="${internip%.*}.0/255.255.255.0"
echo $internip 
echo $privnet

取得目前所有的網路裝置名稱

#!/bin/bash

devs=`ip -o link | cut -f 2 --delimiter=' ' -`
echo "devs="$devs

for i in $devs; do
    dev_name=$(echo ${i%:})
    ip=$(ifconfig $d) && ip=${ip#*inet addr:} && ip=${ip%% *}
    echo "Device Name: "$dev_name
    echo "Device IP: "$ip
    echo "-------------"
done

auto-rar.sh

reference to undefined name 'syntax' Exception of type 'MindTouch.Deki.Script.Runtime.DekiScriptUndefinedNameException' was thrown. (click for details)
Powered by MindTouch Core