使用"whois"命令可以查詢到域名的注冊信息
1)比如查詢www.kevin.com、www.qq.com域名注冊信息(使用whois命令查詢時,需要去掉域名前面的www) [root@bastion ~]# whois kevin.com [root@bastion ~]# whois qq.com 2)查詢ip注冊信息 [root@bastion ~]# whois 112.110.116.15
"syntax error: unexpected end of file"
一般從windows下的shell腳本傳到Linux上可能會出現這樣的問題,是因為Windows和Linux下的行末結束符是不一樣的。即windoes下的dos格式文件傳輸到unix系統時,會在每行的結尾多一個^M,也就是說dos文件中的換行符"\r\n"會被轉換為unix文件中的換行符"\n",而此文件若是一個可執行文件的話,會導致此文件不能被執行。
=======================================================================================================================
案例一:
比如:我有一個test.sh腳本需要上傳到centos系統中執行,但是傳輸到centos系統中,無法正常執行(前提腳本是完全可以執行的,沒有錯誤)。可能原因是在windos系統上使用了類似notepad++的工具修改了可執行文件內容,導致在centos系統下無法正常執行。
案例二:
在本機(win10)測試正常的程序到了線上linux環境下就是跑步起來,tomcat總是卡在loading config.properties這里,換了一個tomcat也是這種情況,以前是沒有問題的。最后懷疑是config.properties文件的問題,然后通過vim查看config.properties文件的fileformat格式,命令":set fileformat",結果顯示的是dos, 最后通過命令修改為":set fileformat=unix"
=======================================================================================================================
這樣先弄清楚一下"回車"和"換行符"的區別:
1)回車"\r"
本義是光標重新回到本行開頭,r的英文return,控制字符可以寫成CR,即Carriage Return
2)換行"\n"
本義是光標往下一行(不一定到下一行行首),n的英文newline,控制字符可以寫成LF,即Line Feed
解決辦法:
1)使用vim打開file.sh腳本文件,進入編輯模式,修改如下:
:set ff=unix (或者:set fileformat=unix)
:wq
2)如果以上步驟要求在一個shell批處理文件中完成,那么該怎么辦?可以這樣:
vi +':w ++ff=unix' +':q' ${file}
這樣一條命令就可以搞定了,但是要嚴格注意上面空格的位置,不能多不能少。
================================================================================
總結:在windows下新建的sh文件,copy到linux下有的會報錯,一般是格式問題。
解決辦法:使用vim編輯器進行一下文件格式fileformat轉換可使用fileformat或簡寫ff。
在vim編輯可執行文件:
set ff 或 set ff? #顯示當前文件格式
set fileformat=unix 或 set ff=unix #設置成unix格式
set ff=dos #設置成dos格式
dos格式文件傳輸到unix系統時,會在每行的結尾多一個^M(/r)
刪除^M的方法:
:%s//r//g
%s/\r//g
sed文本操作命令使用
sed是一個很好的文件處理工具,本身是一個管道命令,主要是以行為單位進行處理,可以將數據行進行替換、刪除、新增、選取等特定工作。
sed命令行格式為:
sed [-nefri] ‘command’ 輸入文本
常用選項:
-n∶使用安靜(silent)模式。在一般 sed 的用法中,所有來自 STDIN的資料一般都會被列出到螢幕上。但如果加上 -n 參數后,則只有經過sed 特殊處理的那一行(或者動作)才會被列出來。
-e∶直接在指令列模式上進行 sed 的動作編輯;
-f∶直接將 sed 的動作寫在一個檔案內, -f filename 則可以執行 filename 內的sed 動作;
-r∶sed 的動作支援的是延伸型正規表示法的語法。(預設是基礎正規表示法語法)
-i∶直接修改讀取的檔案內容,而不是由螢幕輸出。kevin.txt
常用命令:
a ∶新增, a 的后面可以接字串,而這些字串會在新的一行出現(目前的下一行)~
c ∶取代, c 的后面可以接字串,這些字串可以取代 n1,n2 之間的行!
d ∶刪除,因為是刪除啊,所以 d 后面通常不接任何咚咚;
i ∶插入, i 的后面可以接字串,而這些字串會在新的一行出現(目前的上一行);
p ∶列印,亦即將某個選擇的資料印出。通常 p 會與參數 sed -n 一起運作~
s ∶取代,可以直接進行取代的工作哩!通常這個 s 的動作可以搭配正規表示法!例如 1,20s/old/new/g 就是啦!
替換一行中的某部分。s后面的替換符號可以使用/,#,_三種符號
格式:sed 's/要替換的字符串/新的字符串/g' (要替換的字符串可以用正則表達式)
[root@kevin ~]# sed -n '/ruby/p' kevin.txt | sed 's/ruby/bird/g' #替換ruby為bird
[root@kevin ~]# sed -n '/ruby/p' kevin.txt | sed 's#ruby#bird#g' #替換ruby為bird
[root@kevin ~]# sed -n '/ruby/p' kevin.txt | sed 's_ruby_bird_g' #替換ruby為bird
定址
定址用於決定對哪些行進行編輯。地址的形式可以是數字、正則表達式、或二者的結合。
如果沒有指定地址,sed將處理輸入文件的所有行。
地址是一個數字,則表示行號;是“$"符號,則表示最后一行。例如:
[root@kevin ~]# sed -n '3p' datafile
只打印第三行
只顯示指定行范圍的文件內容,例如只查看文件的第100行到第200行
[root@kevin ~]# sed -n '100,200p' mysql_slow_query.log
地址是逗號分隔的,那么需要處理的地址是這兩行之間的范圍(包括這兩行在內)。范圍可以用數字、正則表達式、或二者的組合表示。
[root@kevin ~]# sed '2,5d' datafile
刪除第二到第五行
[root@kevin ~]# sed '/My/,/You/d' datafile
刪除包含"My"的行到包含"You"的行之間的行
[root@kevin ~]# sed '/My/,10d' datafile
刪除包含"My"的行到第十行的內容
示例說明
kevin.txt刪除某行
[root@kevin ~]# sed '1d' kevin.txtkevin.txt #刪除第一行
[root@kevin ~]# sed '$d' kevin.txtkevin.txt #刪除最后一行
[root@kevin ~]# sed '1,2d' kevin.txt #刪除第一行到第二行
[root@kevin ~]# sed '2,$d' kevin.txt #刪除第二行到最后一行
顯示某行
[root@kevin ~]# sed -n '1p' kevin.txt #顯示第一行
[root@kevin ~]# sed -n '$p' kevin.txt #顯示最后一行
[root@kevin ~]# sed -n '1,2p' kevin.txt #顯示第一行到第二行
[root@kevin ~]# sed -n '2,$p' kevin.txt #顯示第二行到最后一行
使用模式進行查詢
[root@kevin ~]# sed -n '/ruby/p' kevin.txt #查詢包括關鍵字ruby所在所有行
[root@kevin ~]# sed -n '/\$/p' kevin.txt #查詢包括關鍵字$所在所有行,使用反斜線\屏蔽特殊含義
增加一行或多行字符串
[root@kevin ~]# cat kevin.txt
kevin.txtHello!
kevin.txtruby is me,welcome to my blog.
kevin.txtend
[root@kevin ~]# sed '1a drink tea' kevin.txt #第一行后增加字符串"drink tea"
kevin.txtHello!
kevin.txtdrink tea
kevin.txtruby is me,welcome to my blog.
kevin.txtend
[root@kevin ~]# sed '1,3a drink tea' kevin.txt #第一行到第三行后增加字符串"drink tea"
kevin.txtHello!
kevin.txtdrink tea
kevin.txtruby is me,welcome to my blog.
kevin.txtdrink tea
kevin.txtend
kevin.txtdrink tea
[root@kevin ~]# sed '1a drink tea\nor coffee' kevin.txt #第一行后增加多行,使用換行符\n
kevin.txtHello!
kevin.txtdrink tea
kevin.txtor coffee
kevin.txtruby is me,welcome to my blog.
kevin.txtend
代替一行或多行
[root@kevin ~]# sed '1c Hi' kevin.txt#第一行代替為Hi
kevin.txtHi
kevin.txtruby is me,welcome to my blog.
kevin.txtend
[root@kevin ~]# sed '1,2c Hi' kevin.txtkevin.txt#第一行到第二行代替為Hi
kevin.txtHi
kevin.txtend
替換一行中的某部分
格式:sed 's/要替換的字符串/新的字符串/g' (要替換的字符串可以用正則表達式)
[root@kevin ~]# sed -n '/ruby/p' kevin.txt | sed 's/ruby/bird/g' #替換ruby為bird
[root@kevin ~]# sed -n '/ruby/p' kevin.txt | sed 's/ruby//g' #刪除ruby
kevin.txt插入
[root@kevin ~]# sed -i '$a bye' kevin.txt #在文件kevin.txt中最后一行直接輸入"bye"
[root@kevin ~]# cat kevin.txt
kevin.txtHello!
kevin.txtruby is me,welcome to my blog.
kevin.txtend
kevin.txtbye
替換:
-e是編輯命令,用於sed執行多個編輯任務的情況下。在下一行開始編輯前,所有的編輯動作將應用到模式緩沖區中的行上。
[root@kevin ~]# sed -e '1,10d' -e 's/My/Your/g' datafile
選項-e用於進行多重編輯。
第一重編輯刪除第1-3行。
第二重編輯將出現的所有My替換為Your。
因為是逐行進行這兩項編輯(即這兩個命令都在模式空間的當前行上執行),所以編輯命令的順序會影響結果。
替換兩個或多個空格為一個空格
[root@kevin ~]# sed 's/[ ][ ]*/ /g' file_name
替換兩個或多個空格為分隔符:
[root@kevin ~]# sed 's/[ ][ ]*/:/g' file_name
如果空格與tkevin.txt共存時用下面的命令進行替換
替換成空格
[root@kevin ~]# sed 's/[[:space:]][[:space:]]*/ /g' filename
替換成分隔符:
[root@kevin ~]# sed 's/[[:space:]][[:space:]]*/:/g' filename
=======================================
sed命令的調用:
在命令行鍵入命令;將sed命令插入腳本文件,然后調用sed;將sed命令插入腳本文件,並使sed腳本可執行
sed [option] sed命令 輸入文件 在命令行使用sed命令,實際命令要加單引號
sed [option] -f sed腳本文件 輸入文件 使用sed腳本文件
sed腳本文件 [option] 輸入文件 第一行具有sed命令解釋器的sed腳本文件
option如下:
n 不打印; sed不寫編輯行到標准輸出,缺省為打印所有行(編輯和未編輯),p命令可以用來打印編輯行
c 下一命令是編輯命令,使用多項編輯時加入此選項
f 如果正在調用sed腳本文件,使用此選項,此選項通知sed一個腳本文件支持所用的sed命令,如
# sed -f myscript.sed input_file 這里myscript.sed即為支持sed命令的文件
使用重定向文件即可保存sed的輸出
使用sed在文本中定位文本的方式:
x x為一行號,比如1
x,y 表示行號范圍從x到y,如2,5表示從第2行到第5行
/pattern/ 查詢包含模式的行,如/disk/或/[a-z]/
/pattern/pattern/ 查詢包含兩個模式的行,如/disk/disks/
/pattern/,x 在給定行號上查詢包含模式的行,如/disk/,3
x,/pattern/ 通過行號和模式查詢匹配行,如 3,/disk/
x,y! 查詢不包含指定行號x和y的行
基本sed編輯命令:
p 打印匹配行 c/ 用新文本替換定位文本
= 顯示文件行號 s 使用替換模式替換相應模式
a/ 在定位行號后附加新文本信息 r 從另一個文本中讀文本
i/ 在定位行號后插入新文本信息 w 寫文本到一個文件
d 刪除定位行 q 第一個模式匹配完成后退出或立即退出
l 顯示與八進制ASCII代碼等價的控制字符 y 傳送字符
n 從另一個文本中讀文本下一行,並附加在下一行 {} 在定位行執行的命令組
g 將模式2粘貼到/pattern n/
基本sed編程舉例:
使用p(rint)顯示行: sed -n '2p' temp.txt 只顯示第2行,使用選項n
打印范圍: sed -n '1,3p' temp.txt 打印第1行到第3行
打印模式: sed -n '/movie/'p temp.txt 打印含movie的行
使用模式和行號查詢: sed -n '3,/movie/'p temp.txt 只在第3行查找movie並打印
顯示整個文件: sed -n '1,$'p temp.txt $為最后一行
任意字符: sed -n '/.*ing/'p temp.txt 注意是.*ing,而不是*ing
打印行號: sed -e '/music/=' temp.txt
附加文本:(創建sed腳本文件)chmod u+x script.sed,運行時./script.sed temp.txt
#!/bin/sed -f
/name1/ a/ #a/表示此處換行添加文本
HERE ADD NEW LINE. #添加的文本內容
插入文本: /name1/ a/ 改成 4 i/ 4表示行號,i插入
修改文本: /name1/ a/ 改成 /name1/ c/ 將修改整行,c修改
刪除文本: sed '1d' temp.txt 或者 sed '1,4d' temp.txt
替換文本: sed 's/source/OKSTR/' temp.txt 將source替換成OKSTR
sed 's//$//g' temp.txt 將文本中所有的$符號全部刪除
sed 's/source/OKSTR/w temp2.txt' temp.txt 將替換后的記錄寫入文件temp2.txt
替換修改字符串: sed 's/source/"ADD BEFORE" &/p' temp.txt
結果將在source字符串前面加上"ADD BEFORE",這里的&表示找到的source字符並保存
sed結果寫入到文件: sed '1,2 w temp2.txt' temp.txt
sed '/name/ w temp2.txt' temp.txt
從文件中讀文本: sed '/name/r temp2.txt' temp.txt
在每列最后加文本: sed 's/[0-9]*/& Pass/g' temp.txt
從shell向sed傳值: echo $NAME | sed "s/go/$REP/g" 注意需要使用雙引號
快速一行命令:
's//.$//g' 刪除以句點結尾行
'-e /abcd/d' 刪除包含abcd的行
's/[][][]*/[]/g' 刪除一個以上空格,用一個空格代替
's/^[][]*//g' 刪除行首空格
's//.[][]*/[]/g' 刪除句號后跟兩個或更多的空格,用一個空格代替
'/^$/d' 刪除空行
's/^.//g' 刪除第一個字符,區別 's//.//g'刪除所有的句點
's/COL/(.../)//g' 刪除緊跟COL的后三個字母
's/^////g' 刪除路徑中第一個/
=================================================
1)使用句點匹配單字符
句點“.”可以匹配任意單字符。“.”可以匹配字符串頭,也可以是中間任意字符。假定正在過濾一個文本文件,對於一個有1 0個字符的腳本集,要求前4個字符之后為X C,匹配操作如下:. . . .X C. . . .
2)在行首以^匹配字符串或字符序列
^只允許在一行的開始匹配字符或單詞。在行首第4個字符為1,匹配操作表示為:^ . . . 1
3)在行尾以$匹配字符串或字符
可以說$與^正相反,它在行尾匹配字符串或字符, $符號放在匹配單詞后。如果在行尾匹配單詞j e t 0 1,操作如下:j e t 0 1 $ 如果只返回包含一個字符的行,操作如下:^ . $
4)使用*匹配字符串中的單字符或其重復序列
使用此特殊字符匹配任意字符或字符串的重復多次表達式。
5)使用/屏蔽一個特殊字符的含義 有
時需要查找一些字符或字符串,而它們包含了系統指定為特殊字符的一個字符。如果要在正則表達式中匹配以* . p a s結尾的所有文件,可做如下操作:/ * / . p a s
6)使用[]匹配一個范圍或集合
使用[ ]匹配特定字符串或字符串集,可以用逗號將括弧內要匹配的不同字符串分開,但並不強制要求這樣做(一些系統提倡在復雜的表達式中使用逗號),
這樣做可以增 加模式的可讀性。使用“ -”表示一個字符串范圍,表明字符串范圍從“ -”左邊字符開始,到“ -”右邊字符結束。假定要匹配任意一個數字,
可以使用:[ 0 1 2 3 4 5 6 7 8 9 ] 要匹配任意字母,則使用:[ A - Z a - z ]表明從A - Z、a - z的字母范圍。
7)使用/{/}匹配模式結果出現的次數
使用*可匹配所有匹配結果任意次,但如果只要指定次數,就應使用/ { / },此模式有三種形式,即:
pattern/{n/} 匹配模式出現n次。
pattern/{n,/} 匹配模式出現最少n次。
pattern/{n,m} 匹配模式出現n到m次之間,n , m為0 - 2 5 5中任意整數。
匹配字母A出現兩次,並以B結尾,操作如下:A / { 2 / } B匹配值為A A B 匹配A至少4次,使用:A / { 4 , / } B
======================
替換單引號為空,可以這樣寫:
sed 's/'"'"'//g'
sed 's/'\''//g'
sed s/\'//g
=====================
在文件的第一行前面插入一行abc
sed -i '1i\abc' urfile
awk命令使用
awk是一個強大的文本分析工具,相對於grep的查找,sed的編輯,awk在其對數據分析並生成報告時,顯得尤為強大。簡單來說awk就是把文件逐行的讀入,
以空格為默認分隔符將每行切片,切開的部分再進行各種分析處理。
awk有3個不同版本: awk、nawk和gawk,未作特別說明,一般指gawk,gawk 是 AWK 的 GNU 版本。
awk其名稱得自於它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母。實際上 AWK 的確擁有自己的語言:
AWK 程序設計語言 , 三位創建者已將它正式定義為“樣式掃描和處理語言”。它允許您創建簡短的程序,這些程序讀取輸入文件、為數據排序、處理數據、
對輸入執行計算以及生成報表,還有無數其他的功能。
使用方法
awk '{pattern + action}' {filenames}
盡管操作可能會很復雜,但語法總是這樣,其中 pattern 表示 AWK 在數據中查找的內容,而 action 是在找到匹配內容時所執行的一系列命令。
花括號({})不需要在程序中始終出現,但它們用於根據特定的模式對一系列指令進行分組。 pattern就是要表示的正則表達式,用斜杠括起來。
awk語言的最基本功能是在文件或者字符串中基於指定規則瀏覽和抽取信息,awk抽取信息后,才能進行其他文本操作。完整的awk腳本通常用來格式化文本
文件中的信息。
通常,awk是以文件的一行為處理單位的。awk每接收文件的一行,然后執行相應的命令,來處理文本。
調用awk
有三種方式調用awk
1)命令行方式
awk [-F field-separator] 'commands' input-file(s)
其中,commands 是真正awk命令,[-F域分隔符]是可選的。 input-file(s) 是待處理的文件。
在awk中,文件的每一行中,由域分隔符分開的每一項稱為一個域。通常,在不指名-F域分隔符的情況下,默認的域分隔符是空格。
2)shell腳本方式
將所有的awk命令插入一個文件,並使awk程序可執行,然后awk命令解釋器作為腳本的首行,一遍通過鍵入腳本名稱來調用。
相當於shell腳本首行的:#!/bin/sh
可以換成:#!/bin/awk
3)將所有的awk命令插入一個單獨文件,然后調用:
awk -f awk-script-file input-file(s)
其中,-f選項加載awk-script-file中的awk腳本,input-file(s)跟上面的是一樣的。
假設last -n 5的輸出如下:
[root@kevin ~]# last -n 5 <==僅取出前五行
root pts/1 192.168.1.100 Tue Feb 10 11:21 still logged in
root pts/1 192.168.1.100 Tue Feb 10 00:46 - 02:28 (01:41)
root pts/1 192.168.1.100 Mon Feb 9 11:41 - 18:30 (06:48)
dmtsai pts/1 192.168.1.100 Mon Feb 9 11:41 - 11:41 (00:00)
root tty1 Fri Sep 5 14:09 - 14:10 (00:01)
如果只是顯示最近登錄的5個帳號
[root@kevin ~]# last -n 5 | awk '{print $1}'
root
root
root
dmtsai
root
awk工作流程是這樣的:
讀入有'\n'換行符分割的一條記錄,然后將記錄按指定的域分隔符划分域,填充域,$0則表示所有域,$1表示第一個域,$n表示第n個域。
默認域分隔符是"空白鍵" 或 "[tab]鍵",所以$1表示登錄用戶,$3表示登錄用戶ip,以此類推。
如果只是顯示/etc/passwd的賬戶
[root@kevin ~]# cat /etc/passwd |awk -F ':' '{print $1}'
root
daemon
bin
sys
這種是awk+action的示例,每行都會執行action{print $1}。
-F指定域分隔符為':'。
如果只是顯示/etc/passwd的賬戶和賬戶對應的shell,而賬戶與shell之間以tab鍵分割
[root@kevin ~]# cat /etc/passwd |awk -F ':' '{print $1"\t"$7}'
root /bin/bash
daemon /bin/sh
bin /bin/sh
sys /bin/sh
如果只是顯示/etc/passwd的賬戶和賬戶對應的shell,而賬戶與shell之間以逗號分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"。
[root@kevin ~]# cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print "blue,/bin/nosh"}'
name,shell
root,/bin/bash
daemon,/bin/sh
bin,/bin/sh
sys,/bin/sh
....
blue,/bin/nosh
awk工作流程是這樣的:
先執行BEGING,然后讀取文件,讀入有/n換行符分割的一條記錄,然后將記錄按指定的域分隔符划分域,填充域,$0則表示所有域,$1表示第一個域,
$n表示第n個域,隨后開始執行模式所對應的動作action。接着開始讀入第二條記錄······直到所有的記錄都讀完,最后執行END操作。
搜索/etc/passwd有root關鍵字的所有行
[root@kevin ~]# awk -F: '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
這種是pattern的使用示例,匹配了pattern(這里是root)的行才會執行action(沒有指定action,默認輸出每行的內容)。
搜索支持正則,例如找root開頭的: awk -F: '/^root/' /etc/passwd
搜索/etc/passwd有root關鍵字的所有行,並顯示對應的shell
[root@kevin ~]# awk -F: '/root/{print $7}' /etc/passwd
/bin/bash
這里指定了action{print $7}
awk內置變量
awk有許多內置變量用來設置環境信息,這些變量可以被改變,下面給出了最常用的一些變量。
ARGC 命令行參數個數
ARGV 命令行參數排列
ENVIRON 支持隊列中系統環境變量的使用
FILENAME awk瀏覽的文件名
FNR 瀏覽文件的記錄數
FS 設置輸入域分隔符,等價於命令行 -F選項
NF 瀏覽記錄的域的個數
NR 已讀的記錄數
OFS 輸出域分隔符
ORS 輸出記錄分隔符
RS 控制記錄分隔符
此外,$0變量是指整條記錄。$1表示當前行的第一個域,$2表示當前行的第二個域,......以此類推。
統計/etc/passwd:文件名,每行的行號,每行的列數,對應的完整行內容:
[root@kevin ~]# awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh
filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh
filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh
使用printf替代print,可以讓代碼更加簡潔,易讀
[root@kevin ~]# awk -F ':' '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
print和printf
awk中同時提供了print和printf兩種打印輸出的函數。
其中print函數的參數可以是變量、數值或者字符串。字符串必須用雙引號引用,參數用逗號分隔。如果沒有逗號,參數就串聯在一起而無法區分。
這里,逗號的作用與輸出文件的分隔符的作用是一樣的,只是后者是空格而已。
printf函數,其用法和c語言中printf基本相似,可以格式化字符串,輸出復雜時,printf更加好用,代碼更易懂。
awk編程:變量和賦值
除了awk的內置變量,awk還可以自定義變量。
下面統計/etc/passwd的賬戶人數
[root@kevin ~]# awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
......
user count is 40
count是自定義變量。之前的action{}里都是只有一個print,其實print只是一個語句,而action{}可以有多個語句,以;號隔開。
這里沒有初始化count,雖然默認是0,但是妥當的做法還是初始化為0:
[root@kevin ~]# awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd
[start]user count is 0
root:x:0:0:root:/root:/bin/bash
...
[end]user count is 40
統計某個文件夾下的文件占用的字節數
[root@kevin ~]# ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size}'
[end]size is 8657198
如果以M為單位顯示:
[root@kevin ~]# ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size/1024/1024,"M"}'
[end]size is 8.25889 M
注意,統計不包括文件夾的子目錄。
條件語句
awk中的條件語句是從C語言中借鑒來的,見如下聲明方式:
if (expression) {
statement;
statement;
... ...
}
if (expression) {
statement;
} else {
statement2;
}
if (expression) {
statement1;
} else if (expression1) {
statement2;
} else {
statement3;
}
統計某個文件夾下的文件占用的字節數,過濾4096大小的文件(一般都是文件夾):
[root@kevin ~]# ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}'
[start]size is 0
[end]size is 0.0610514 M
循環語句
awk中的循環語句同樣借鑒於C語言,支持while、do/while、for、break、continue,這些關鍵字的語義和C語言中的語義完全相同。
數組
因為awk中數組的下標可以是數字和字母,數組的下標通常被稱為關鍵字(key)。值和關鍵字都存儲在內部的一張針對key/value應用hash的表格里。
由於hash不是順序存儲,因此在顯示數組內容時會發現,它們並不是按照你預料的順序顯示出來的。數組和變量一樣,都是在使用時自動創建的,awk
也同樣會自動判斷其存儲的是數字還是字符串。一般而言,awk中的數組用來從記錄中收集信息,可以用於計算總和、統計單詞以及跟蹤模板被匹配的次數等。
顯示/etc/passwd的賬戶
[root@kevin ~]# awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
0 root
1 daemon
2 bin
3 sys
4 sync
5 games
......
這里使用for循環遍歷數組
grep命令:從文件中查找匹配模式的行
1.作用
Linux系統中grep命令是一種強大的文本搜索工具,它能使用正則表達式搜索文本,並把匹 配的行打印出來。grep全稱是Global Regular Expression Print,表示全局正則表達式版本,它的使用權限是所有用戶。
2.格式
grep [options]
3.主要參數
[options]主要參數:
-c:只輸出匹配行的計數。
-I:不區分大 小寫(只適用於單字符)。
-h:查詢多文件時不顯示文件名。
-l:查詢多文件時只輸出包含匹配字符的文件名。
-n:顯示匹配行及 行號。
-s:不顯示不存在或無匹配文本的錯誤信息。
-v:顯示不包含匹配文本的所有行。
pattern正則表達式主要參數:
\: 忽略正則表達式中特殊字符的原有含義。
^:匹配正則表達式的開始行。
$: 匹配正則表達式的結束行。
\<:從匹配正則表達 式的行開始。
\>:到匹配正則表達式的行結束。
[ ]:單個字符,如[A]即A符合要求 。
[ - ]:范圍,如[A-Z],即A、B、C一直到Z都符合要求 。
。:所有的單個字符。
* :有字符,長度可以為0。
grep -v 過濾
grep -c 打印關鍵字符所在的行數
grep -An 打印關鍵字符所在的行的后n行內容
grep -Bn 打印關鍵字符所在的行的前n行內容
grep -Cn 打印關鍵字符所在的行的前后各n行內容
cat filename |grep "abc"
fgrep -R "abc" ./*
4.grep命令使用簡單實例
[root@kevin ~]# grep ‘test’ d*
顯示所有以d開頭的文件中包含 test的行。
[root@kevin ~]# grep ‘test’ aa bb cc
顯示在aa,bb,cc文件中匹配test的行。
[root@kevin ~]# grep ‘[a-z]\{5\}’ aa
顯示所有包含每個字符串至少有5個連續小寫字符的字符串的行。
[root@kevin ~]# grep ‘w\(es\)t.*\1′ aa
如果west被匹配,則es就被存儲到內存中,並標記為1,然后搜索任意個字符(.*),這些字符后面緊跟着 另外一個es(\1),找到就顯示該行。
如果用egrep或grep -E,就不用”\”號進行轉義,直接寫成’w(es)t.*\1′就可以了。
5.grep命令使用復雜實例
假設您正在’/usr/src/Linux/Doc’目錄下搜索帶字符 串’magic’的文件:
[root@kevin ~]# grep magic /usr/src/Linux/Doc/*
sysrq.txt:* How do I enable the magic SysRQ key?
sysrq.txt:* How do I use the magic SysRQ key?
其中文件’sysrp.txt’包含該字符串,討論的是 SysRQ 的功能。
默認情況下,’grep’只搜索當前目錄。如果 此目錄下有許多子目錄,’grep’會以如下形式列出:
grep: sound: Is a directory
這可能會使’grep’ 的輸出難於閱讀。這里有兩種解決的辦法:
明確要求搜索子目錄:grep -r
或忽略子目錄:grep -d skip
如果有很多 輸出時,您可以通過管道將其轉到’less’上閱讀:
[root@kevin ~]# grep magic /usr/src/Linux/Documentation/* | less
這樣,您就可以更方便地閱讀。
有一點要注意,
您必需提供一個文件過濾方式(搜索全部文件的話用 *)。如果您忘了,’grep’會一直等着,直到該程序被中斷。
如果您遇到了這樣的情況,按 <CTRL c> ,然后再試。
下面還有一些有意思的命令行參數:
grep -i pattern files :不區分大小寫地搜索。默認情況區分大小寫,
grep -l pattern files :只列出匹配的文件名,
grep -L pattern files :列出不匹配的文件名,
grep -w pattern files :只匹配整個單詞,而不是字符串的一部分(如匹配’magic’,而不是’magical’),
grep -C number pattern files :匹配的上下文分別顯示[number]行,
grep pattern1 | pattern2 files :顯示匹配 pattern1 或 pattern2 的行,
grep pattern1 files | grep pattern2 :顯示既匹配 pattern1 又匹配 pattern2 的行。
grep -n pattern files 即可顯示行號信息
grep -c pattern files 即可查找總行數
這里還有些用於搜索的特殊符號:
\< 和 \> 分別標注單詞的開始與結尾。
例如:
grep man * 會匹配 ‘Batman’、’manic’、’man’等,
grep ‘\<man’ * 匹配’manic’和’man’,但不是’Batman’,
grep ‘\<man\>’ 只匹配’man’,而不是’Batman’或’manic’等其他的字符串。
‘^’:指匹配的字符串在行首,
‘$’:指匹配的字符串在行 尾,
==============grep、fgrep、egrep的區別=================
者都是搜索工具,但功能上有區別。
1)首先,grep支持的是標准正則表達式。
2)fgrep,不支持正則表達式,只用於匹配固定字符串。
grep把模式當做正則表達式看,fgrep把模式當做固定字符串看,所以后者要比前者速度快,當然同時后者的搜索功能要弱於前者。
3)egrep:為grep 的擴充版本, 改良了許多傳統 grep 不能或不便的操作. 比如:
- grep 之下不支持 ? 與 + 這兩種 modifier, 但 egrep 則可。
- grep 不支持 a|b 或 (abc|xyz) 這類"或一"比對, 但 egrep 則可。
- grep 在處理 {n,m} 時, 需用 \{ 與 \} 處理, 但 egrep 則不需。
===========================================
示例說明
[root@kevin ~]# ps -ef | grep in.telnetd
root 19955 181 0 13:43:53 ? 0:00 in.telnetd
[root@kevin ~]# more size.txt size文件的內容
b124230
b034325
a081016
m7187998
m7282064
a022021
a061048
m9324822
b103303
a013386
b044525
m8987131
B081016
M45678
B103303
BADc2345
[root@kevin ~]# more size.txt | grep '[a-b]' 范圍 ;如[A-Z]即A,B,C一直到Z都符合要求
b124230
b034325
a081016
a022021
a061048
b103303
a013386
b044525
[root@kevin ~]# more size.txt | grep '[a-b]'*
b124230
b034325
a081016
m7187998
m7282064
a022021
a061048
m9324822
b103303
a013386
b044525
m8987131
B081016
M45678
B103303
BADc2345
[root@kevin ~]# more size.txt | grep 'b' #單個字符;如[b] 即b符合要求
b124230
b034325
b103303
b044525
[root@kevin ~]# more size.txt | grep '[bB]' #b或者B
b124230
b034325
b103303
b044525
B081016
B103303
BADc2345
[root@kevin ~]# grep 'root' /etc/group
root::0:root
bin::2:root,bin,daemon
sys::3:root,bin,sys,adm
adm::4:root,adm,daemon
uucp::5:root,uucp
mail::6:root
tty::7:root,tty,adm
lp::8:root,lp,adm
nuucp::9:root,nuucp
daemon::12:root,daemon
[root@kevin ~]# grep '^root' /etc/group #匹配正則表達式的開始行
root::0:root
[root@kevin ~]# grep 'uucp' /etc/group
uucp::5:root,uucp
nuucp::9:root,nuucp
[root@kevin ~]# grep '\<uucp' /etc/group
uucp::5:root,uucp
[root@kevin ~]# grep 'root[root@kevin ~]#' /etc/group #匹配正則表達式的結束行
root::0:root
mail::6:root
[root@kevin ~]# more size.txt | grep -i 'b1..*3' #忽略大小寫
b124230
b103303
B103303
[root@kevin ~]# more size.txt | grep -iv 'b1..*3' #查找不包含匹配項的行
b034325
a081016
m7187998
m7282064
a022021
a061048
m9324822
a013386
b044525
m8987131
B081016
M45678
BADc2345
[root@kevin ~]# more size.txt | grep -in 'b1..*3'
1:b124230
9:b103303
15:B103303
[root@kevin ~]# grep '[root@kevin ~]#' /etc/init.d/nfs.server | wc -l
128
[root@kevin ~]# grep '\[root@kevin ~]#' /etc/init.d/nfs.server | wc –l #忽略正則表達式中特殊字符的原有含義
15
[root@kevin ~]# grep '\$' /etc/init.d/nfs.server
case "$1" in
>/tmp/sharetab.$$
[ "x$fstype" != xnfs ] &&
echo "$path\t$res\t$fstype\t$opts\t$desc"
>>/tmp/sharetab.$$
/usr/bin/touch -r /etc/dfs/sharetab /tmp/sharetab.$$
/usr/bin/mv -f /tmp/sharetab.$$ /etc/dfs/sharetab
if [ -f /etc/dfs/dfstab ] && /usr/bin/egrep -v '^[ ]*(#|$)'
if [ $startnfsd -eq 0 -a -f /etc/rmmount.conf ] &&
if [ $startnfsd -ne 0 ]; then
elif [ ! -n "$_INIT_RUN_LEVEL" ]; then
while [ $wtime -gt 0 ]; do
wtime=`expr $wtime - 1`
if [ $wtime -eq 0 ]; then
echo "Usage: $0 { start | stop }"
[root@kevin ~]# more size.txt
the test file
their are files
The end
[root@kevin ~]# grep 'the' size.txt
the test file
their are files
[root@kevin ~]# grep '\<the' size.txt
the test file
their are files
[root@kevin ~]# grep 'the\>' size.txt
the test file
[root@kevin ~]# grep '\<the\>' size.txt
the test file
[root@kevin ~]# grep '\<[Tt]he\>' size.txt
the test file
多個文件查詢
[root@kevin ~]# grep "sort" *.txt #見文件名的匹配
行匹配:輸出匹配行的計數
[root@kevin ~]# grep -c "48" kevin.txt #輸出文檔中含有48字符的行數
顯示匹配行和行數
[root@kevin ~]# grep -n "48" kevin.txt #顯示所有匹配48的行和行號
顯示非匹配的行
[root@kevin ~]# grep -vn "48" kevin.txt #輸出所有不包含48的行
顯示非匹配的行
[root@kevin ~]# grep -vn "48" kevin.txt #輸出所有不包含48的行
大小寫敏感
[root@kevin ~]# grep -i "ab" kevin.txt #輸出所有含有ab或Ab的字符串的行
====================================
正則表達式的應用 (注意:最好把正則表達式用單引號括起來)
[root@kevin ~]# grep '[239].' kevin.txt #輸出所有含有以2,3或9開頭的,並且是兩個數字的行
不匹配測試
[root@kevin ~]# grep '^[^48]' kevin.txt #不匹配行首是48的行
使用擴展模式匹配
[root@kevin ~]# grep -E '219|216' kevin.txt
使用類名
可以使用國際模式匹配的類名:
[[:upper:]] [A-Z]
[[:lower:]] [a-z]
[[:digit:]] [0-9]
[[:alnum:]] [0-9a-zA-Z]
[[:space:]] 空格或tab
[[:alpha:]] [a-zA-Z]
[root@kevin ~]# grep '5[[:upper:]][[:upper:]]' kevin.txt #查詢以5開頭以兩個大寫字母結尾的行
cat、more、less、tail、head命令
cat 是一個文本文件(查看)和(連接)工具,通常與more搭配使用,與more不同的是cat可以合並文件。查看一個文件的內容,用cat比較簡單, 就是cat后面直接接文件名。 cat [選項] [文件]... 選項 -A, --show-all 等價於 -vET -b, --number-nonblank 對非空輸出行編號 -e 等價於 -vE -E, --show-ends 在每行結束處顯示 $ -n, --number 對輸出的所有行編號 -s, --squeeze-blank 不輸出多行空行 -t 與 -vT 等價 -T, --show-tabs 將跳格字符顯示為 ^I -u (被忽略) -v, --show-nonprinting 使用 ^ 和 M- 引用,除了 LFD 和 TAB 之外 --help 顯示此幫助信息並離開 cat 查看文件內容實例: [root@kevin ~]# cat /etc/profile //查看/etc/目錄下的profile文件內容; [root@kevin ~]# cat -b /etc/fstab //查看/etc/目錄下的profile內容,並且對非空白行進行編號,行號從1開始; [root@kevin ~]# cat -n /etc/profile //對/etc目錄中的profile的所有的行(包括空白行)進行編號輸出顯示; [root@kevin ~]# cat -E /etc/profile //查看/etc/下的profile內容,並且在每行的結尾處附加$符號; cat 加參數-n 和nl工具差不多,文件內容輸出的同時,都會在每行前面加上行號; [root@kevin ~]# cat -n /etc/profile [root@kevin ~]# nl /etc/profile cat 可以同時顯示多個文件的內容,比如我們可以在一個cat命令上同時顯示兩個文件的內容; [root@kevin ~]# cat /etc/fstab /etc/profile cat 對於內容極大的文件來說,可以通過管道|傳送到more 工具,然后一頁一頁的查看; [root@kevin ~]# cat /etc/fstab /etc/profile | more cat 的創建、連接文件功能實例: cat 有創建文件的功能,創建文件后,要以EOF或STOP結束; [root@kevin ~]# cat > kevin.txt<< EOF > 我來測試 cat 創建文件,並且為文件輸入內容; > 北京是個好地方; > EOF [root@kevin ~]# cat kevin.txt 我來測試 cat 創建文件,並且為文件輸入內容; 北京是個好地方; cat 還有向已存在的文件追加內容的功能; [root@kevin ~]# cat grace.txt I am BeiNanNanBei From grace.Org . 我正在為cat命令寫文檔 [root@kevin ~]# cat >> grace.txt << EOF > 我來測試cat向文檔追加內容的功能; > OK? > OK~ > 北京你好 > EOF [root@kevin ~]# cat grace.txt //查看文件內容,看是否追回成功。 I am BeiNanNanBei From grace.Org . 我正在為cat命令寫文檔 我來測試cat向文檔追加內容的功能; OK? OK~ 北京你好 cat 連接多個文件的內容並且輸出到一個新文件中; 假設我們有sir01.txt、sir02.tx和sir03.txt ,並且內容如下; [root@kevin ~]# cat sir01.txt 123456 i am testing [root@kevin ~]# cat sir02.txt 56789 BeiNan Tested [root@kevin ~]# cat sir03.txt 09876 grace.org testing 我想通過cat 把sir01.txt、sir02.txt及sir03.txt 三個文件連接在一起(也就是說把這三個文件的內容都接在一起)並輸出到一個新的文件sir04.txt 中。 注意: 其原理是把三個文件的內容連接起來,然后創建sir04.txt文件,並且把幾個文件的內容同時寫入sir04.txt中。特別值得一提的是,如果您輸入到一個已經 存在的sir04.txt 文件,會把sir04.txt內容清空。 [root@kevin ~]# cat sir01.txt sir02.txt sir03.txt > sir04.txt [root@kevin ~]# more sir04.txt 123456 i am testing 56789 BeiNan Tested 09876 grace.org testing cat 把一個或多個已存在的文件內容,追加到一個已存在的文件中 [root@kevin ~]# cat sir00.txt grace.org forever [root@kevin ~]# cat sir01.txt sir02.txt sir03.txt >> sir00.txt [root@kevin ~]# cat sir00.txt grace.org forever 123456 i am testing 56789 BeiNan Tested 09876 grace.org testing ====================================================== more 是我們最常用的工具之一,最常用的就是顯示輸出的內容,然后根據窗口的大小進行分頁顯示,然后還能提示文件的百分比; 參數如下: +num 從第num行開始顯示; -num 定義屏幕大小,為num行; +/pattern 從pattern 前兩行開始顯示; -c 從頂部清屏然后顯示; -d 提示Press space to continue, 'q' to quit.(按空格鍵繼續,按q鍵退出),禁用響鈴功能; -l 忽略Ctrl+l (換頁)字符; -p 通過清除窗口而不是滾屏來對文件進行換頁。和-c參數有點相似; -s 把連續的多個空行顯示為一行; -u 把文件內容中的下划線去掉退出more的動作指令是q more 的參數應用舉例: [root@kevin ~]# more -dc /etc/profile //顯示提示,並從終端或控制台頂部顯示; [root@kevin ~]# more +4 /etc/profile //從profile的第4行開始顯示; [root@kevin ~]# more -4 /etc/profile //每屏顯示4行; [root@kevin ~]# more +/MAIL /etc/profile //從profile中的第一個MAIL單詞的前兩行開始顯示; more 的動作指令: 我們查看一個內容較大的文件時,要用到more的動作指令,比如ctrl+f(或空格鍵) 是向下顯示一屏,ctrl+b是返回上一屏; Enter鍵可以向下滾動顯示n行,要通過定,默認為1行; 我們只說幾個常用的; 自己嘗試一下就知道了; Enter 向下n行,需要定義,默認為1行; Ctrl+f 向下滾動一屏; 空格鍵 向下滾動一屏; Ctrl+b 返回上一屏; = 輸出當前行的行號; :f 輸出文件名和當前行的行號; v 調用vi編輯器; ! 命令 調用Shell,並執行命令; q 退出more當我們查看某一文件時,想調用vi來編輯它,不要忘記了v動作指令,這是比較方便的; 其它命令通過管道和more結合的運用例子: 比如我們列一個目錄下的文件,由於內容太多,我們應該學會用more來分頁顯示。這得和管道 | 結合起來,比如: [root@kevin ~]# ls -l /etc |more ======================================================= less 查看文件內容 工具 less 工具也是對文件或其它輸出進行分頁顯示的工具,應該說是linux正統查看文件內容的工具,功能極其強大;您是初學者,我建議您用less。 由於less的內容太多,我們把最常用的介紹一下; 常用參數 -c 從頂部(從上到下)刷新屏幕,並顯示文件內容。而不是通過底部滾動完成刷新; -f 強制打開文件,二進制文件顯示時,不提示警告; -i 搜索時忽略大小寫;除非搜索串中包含大寫字母; -I 搜索時忽略大小寫,除非搜索串中包含小寫字母; -m 顯示讀取文件的百分比; -M 顯法讀取文件的百分比、行號及總行數; -N 在每行前輸出行號; -p pattern 搜索pattern;比如在/etc/profile搜索單詞MAIL,就用 less -p MAIL /etc/profile -s 把連續多個空白行作為一個空白行顯示; -Q 在終端下不響鈴; 比如:我們在顯示/etc/profile的內容時,讓其顯示行號; [root@kevin ~]# less -N /etc/profile less的動作命令: 進入less后,我們得學幾個動作,這樣更方便 我們查閱文件內容;最應該記住的命令就是q,這個能讓less終止查看文件退出; 動作: 回車鍵 向下移動一行; y 向上移動一行; 空格鍵 向下滾動一屏; b 向上滾動一屏; d 向下滾動半屏; h less的幫助; u 向上洋動半屏; w 可以指定顯示哪行開始顯示,是從指定數字的下一行顯示;比如指定的是6,那就從第7行顯示; g 跳到第一行; G 跳到最后一行; p n% 跳到n%,比如 10%,也就是說比整個文件內容的10%處開始顯示; /pattern 搜索pattern ,比如 /MAIL表示在文件中搜索MAIL單詞; v 調用vi編輯器; q 退出less !command 調用SHELL,可以運行命令;比如!ls 顯示當前列當前目錄下的所有文件; 就less的動作來說,內容太多了,用的時候查一查man less是最好的。在這里就不舉例子了; ========================================================== head 工具,顯示文件內容的前幾行 head 是顯示一個文件的內容的前多少行; 用法比較簡單; head -n 行數值 文件名; 比如我們顯示/etc/profile的前10行內容,應該是: [root@kevin ~]# head -n 10 /etc/profile ========================================================= tail 工具,顯示文件內容的最后幾行 tail 是顯示一個文件的內容的最后多少行; 用法比較簡單; tail -n 行數值 文件名; 比如我們顯示/etc/profile的最后5行內容,應該是: [root@kevin ~]# tail -n 5 /etc/profile tail -f /var/log/syslog 顯示文件 syslog 的后十行內容並在文件內容增加后,且自動顯示新增的文件內容。
cut命令:打印每行特定范圍內內容
cut是一個選取命令,就是將一段數據經過分析,取出我們想要的。一般來說,選取信息通常是針對“行”來進行分析的,並不是整篇信息分析的。
其語法格式為:
cut [-bn] [file] 或 cut [-c] [file] 或 cut [-df] [file]
使用說明
cut 命令從文件的每一行剪切字節、字符和字段並將這些字節、字符和字段寫至標准輸出。
如果不指定 File 參數,cut 命令將讀取標准輸入。必須指定 -b、-c 或 -f 標志之一。
主要參數
-b :以字節為單位進行分割。這些字節位置將忽略多字節字符邊界,除非也指定了 -n 標志。
-c :以字符為單位進行分割。
-d :自定義分隔符,默認為制表符。
-f :與-d一起使用,指定顯示哪個區域。
-n :取消分割多字節字符。僅和 -b 標志一起使用。如果字符的最后一個字節落在由 -b 標志的 List 參數指示的<br />范圍之內,該字符將被寫出;否則,該字符將被排除。
cut一般以什么為依據呢? 也就是說,我怎么告訴cut我想定位到的剪切內容呢?
cut命令主要是接受三個定位方法:
第一,字節(bytes),用選項-b
第二,字符(characters),用選項-c
第三,域(fields),用選項-f
=========================================
cut在取列內容的時候和awk相識
awk -F"" '{print $n}' 以-F后的引號內的內容為列的分隔符,打印第n行
cut -d"" -fn 以-d后的引號內的內容為列的分隔符,打印第n行
比如打印a.txt文件中以空格為列的分隔符,打印第5行
awk -F" " '{print $5}' a.txt 當以空格為分隔符的時候,-F" " 可以省去
cut -d" " -f5 a.txt
=========================================
以“字節”定位
舉個例子吧,當你執行ps命令時,會輸出類似如下的內容:
[root@kevin ~]# who
rocrocket :0 2009-01-08 11:07
rocrocket pts/0 2009-01-08 11:23 (:0.0)
rocrocket pts/1 2009-01-08 14:15 (:0.0)
如果我們想提取每一行的第3個字節,就這樣:
[root@kevin ~]# who|cut -b 3
c
c
c
如果“字節”定位中,我想提取第3,第4、第5和第8個字節,怎么辦?
-b支持形如3-5的寫法,而且多個定位之間用逗號隔開就成了。看看例子吧:
[root@kevin ~]# who|cut -b 3-5,8
croe
croe
croe
但有一點要注意,cut命令如果使用了-b選項,那么執行此命令時,cut會先把-b后面所有的定位進行從小到大排序,然后再提取。
可不能顛倒定位的順序哦。這個例子就可以說明這個問題:
[root@kevin ~]# who|cut -b 8,3-5
croe
croe
croe
還有哪些類似“3-5”這樣的小技巧,列舉一下吧!
[root@kevin ~]# who
rocrocket :0 2009-01-08 11:07
rocrocket pts/0 2009-01-08 11:23 (:0.0)
rocrocket pts/1 2009-01-08 14:15 (:0.0)
[root@kevin ~]# who|cut -b -3
roc
roc
roc
[root@kevin ~]# who|cut -b 3-
crocket :0 2009-01-08 11:07
crocket pts/0 2009-01-08 11:23 (:0.0)
crocket pts/1 2009-01-08 14:15 (:0.0)
-3表示從第一個字節到第三個字節,而3-表示從第三個字節到行尾。如果你細心,你可以看到這兩種情況下,都包括了第三個字節“c”。
如果我執行who|cut -b -3,3-,你覺得會如何呢?答案是輸出整行,不會出現連續兩個重疊的c的。看:
[root@kevin ~]# who|cut -b -3,3-
rocrocket :0 2009-01-08 11:07
rocrocket pts/0 2009-01-08 11:23 (:0.0)
rocrocket pts/1 2009-01-08 14:15 (:0.0)
給個以字符為定位標志的最簡單的例子吧!
下面例子你似曾相識,提取第3,第4,第5和第8個字符:
[root@kevin ~]# who|cut -c 3-5,8
croe
croe
croe
不過,看着怎么和-b沒有什么區別啊?莫非-b和-c作用一樣? 其實不然,看似相同,只是因為這個例子舉的不好,who輸出的都是單字節字符,
所以用-b和-c沒有區別,如果你提取中文,區別就看出來了,來,看看中文提取的情況:
[root@kevin ~]# cat cut_ch.txt
星期一
星期二
星期三
星期四
[root@kevin ~]# cut -b 3 cut_ch.txt
�
�
�
�
[root@kevin ~]# cut -c 3 cut_ch.txt
一
二
三
四
看到了吧,用-c則會以字符為單位,輸出正常;而-b只會傻傻的以字節(8位二進制位)來計算,輸出就是亂碼。
既然提到了這個知識點,就再補充一句,如果你學有余力,就提高一下。
當遇到多字節字符時,可以使用-n選項,-n用於告訴cut不要將多字節字符拆開。例子如下:
[root@kevin ~]# cat cut_ch.txt |cut -b 2
�
�
�
�
[root@kevin ~]# cat cut_ch.txt |cut -nb 2
[root@kevin ~]# cat cut_ch.txt |cut -nb 1,2,3
星
星
星
星
域是怎么回事呢?解釋解釋:)
為什么會有“域”的提取呢,因為剛才提到的-b和-c只能在固定格式的文檔中提取信息,而對於非固定格式的信息則束手無策。這時候“域”就派上用場了。
如果你觀察過/etc/passwd文件,你會發現,它並不像who的輸出信息那樣具有固定格式,而是比較零散的排放。但是,冒號在這個文件的每一行中都
起到了非常重要的作用,冒號用來隔開每一個項。
cut命令提供了這樣的提取方式,具體的說就是設置“間隔符”,再設置“提取第幾個域”,就OK了!
以/etc/passwd的前五行內容為例:
[root@kevin ~]# cat /etc/passwd|head -n 5
root:x:0:0:root:/root:/bin/bash
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
[root@kevin ~]# cat /etc/passwd|head -n 5|cut -d : -f 1
root
bin
daemon
adm
lp
用-d來設置間隔符為冒號,然后用-f來設置我要取的是第一個域,再按回車,所有的用戶名就都列出來了!
當然,在設定-f時,也可以使用例如3-5或者4-類似的格式:
[root@kevin ~]# cat /etc/passwd|head -n 5|cut -d : -f 1,3-5
root:0:0:root
bin:1:1:bin
daemon:2:2:daemon
adm:3:4:adm
lp:4:7:lp
[root@kevin ~]# cat /etc/passwd|head -n 5|cut -d : -f 1,3-5,7
root:0:0:root:/bin/bash
bin:1:1:bin:/sbin/nologin
daemon:2:2:daemon:/sbin/nologin
adm:3:4:adm:/sbin/nologin
lp:4:7:lp:/sbin/nologin
[root@kevin ~]# cat /etc/passwd|head -n 5|cut -d : -f -2
root:x
bin:x
daemon:x
adm:x
lp:x
如果遇到空格和制表符時,怎么分辨呢?我覺得有點亂,怎么辦?
有時候制表符確實很難辨認,有一個方法可以看出一段空格到底是由若干個空格組成的還是由一個制表符組成的。
[root@kevin ~]# cat tab_space.txt
this is tab finish.
this is several space finish.
[root@kevin ~]# sed -n l tab_space.txt
this is tab\tfinish.$
this is several space finish.$
如果是制表符(TAB),那么會顯示為\t符號,如果是空格,就會原樣顯示。
通過此方法即可以判斷制表符和空格了。
注意,上面sed -n后面的字符是L的小寫字母哦,不要看錯。
我應該在cut -d中用什么符號來設定制表符或空格呢?
其實cut的-d選項的默認間隔符就是制表符,所以當你就是要使用制表符的時候,完全就可以省略-d選項,而直接用-f來取域就可以了。
如果你設定一個空格為間隔符,那么就這樣:
[root@kevin ~]# cat tab_space.txt |cut -d ' ' -f 1
this
this
注意,兩個單引號之間可確實要有一個空格哦,不能偷懶。
而且,你只能在-d后面設置一個空格,可不許設置多個空格,因為cut只允許間隔符是一個字符。
[root@kevin ~]# cat tab_space.txt |cut -d ' ' -f 1
cut: the delimiter must be a single character
Try `cut --help' for more information.
cut有哪些缺陷和不足?
猜出來了吧?對,就是在處理多空格時。
如果文件里面的某些域是由若干個空格來間隔的,那么用cut就有點麻煩了,因為cut只擅長處理“以一個字符間隔”的文本內容。
tr命令:刪除,去重,替換文本內容
可以把tr看作為一個簡化的sed工具,tr表示為:translate。tr命令主要用於實現以下兩個功能 替換操作的字符串轉換。 刪除操作的字符串轉換,可以很容易的刪除一些控制字符或者是空行。 tr命令能夠實現的功能,都能夠用sed命令來實現。但就具體的替換功能來說,tr用起來更容易,也比較簡單。 一,命令格式 tr [option] ["string1"] ["string2"] < file 常用的選項有: 默認選項。就是沒有任何選項的時候,tr默認為替換操作,就是將string1在文件中出現的字符替換為string2中的字符,這里要注意的是替換關系。 -c選項,用string1中字符的補集替換string1,這里的字符集為ASCII。 -d選項,刪除文件中所有在string1中出現的字符。 -s選項,刪除文件中重復並且在string1中出現的字符,只保留一個。 -c選項在使用時,只是將string1替換為現在的補集 [root@kevin ~]# echo "hello world,root,2012" | tr -c "0-9" "*" *****************2012* 可以看出,我們使用0-9,添加-c選項后,會把0-9替換為其補集,這時補集自然不包含0-9,而包含很多其它的字符,接下來就把所有的其它字符都替換成*號, 但不包含數字。 如果只需要替換數字的話: [root@kevin ~]# echo "hello world,root,2012" | tr "0-9" "*" hello world,root,**** 二,字符串的取值范圍 指定string或string2的內容時,只能使用單字符或字符串范圍或列表。 [a-z] a-z內的字符組成的字符串。 [A-Z] A-Z內的字符組成的字符串。 [0-9] 數字串。 \octal 一個三位的八進制數,對應有效的ASCII字符。 [O*n] 表示字符O重復出現指定次數n。因此[O*2]匹配OO的字符串。 三,控制字符的不同表達方式 速記符 含義 八進制方式 \a Ctrl-G 鈴聲\007 \b Ctrl-H 退格符\010 \f Ctrl-L 走行換頁\014 \n Ctrl-J 新行\012 \r Ctrl-M 回車\015 \t Ctrl-I tab鍵\011 \v Ctrl-X \030 注意這些控制字符,如果想在linux下輸入,如我們可能需要輸入^M這種字符,只需ctrl+V+M同時按下即可。 四,字符替換 這是tr的默認操作,先看下面的命令和輸出 [root@kevin ~]# echo "hello world" | tr "a-z" "A-Z" HELLO WORLD [root@kevin ~]# echo "hello world" | tr "a-l" "A-Z" HELLo worLD [root@kevin ~]# echo "hello world" | tr "a-z" "A-H" HEHHH HHHHD 第一行輸出就是將小寫換成大寫。 第二行輸出將小寫中的a-l分別換成A-L,而將小寫中的l以后的字符都不替換。 第三行輸出將小寫中的a-h換成A-H,而h以后的字符都換成H,因為后者的替換空間沒有前面的字符空間大,所以就重復后面的H, 相當於后面的字符是A-HHH......HHHHH。 如果我們想要進行大小寫轉換,可以按下面的輸入: tr "a-z" "A-Z" < inputfile 五,去除重復字符 這個時候,所用的選項是-s選項,如: [root@kevin ~]# echo "hello world,root" | tr -s "ao" hello world,rot [root@kevin ~]# echo "hello world,root" | tr -s "lo" helo world,rot [root@kevin ~]# echo "hello world,root" | tr -s "a-z" helo world,rot [root@kevin ~]# echo "hello world,root" | tr -s "0-9" hello world,root 第一行表示將輸入字符串中的包含在"ao"字符集中的重復字符去掉,只留一個。因為"hello world,root",只有o滿足條件,所以將root變成rot,把中間的兩個o變成一個。 第二行將hello和root兩個字符都壓縮了。 第三行表示將a-z中的除復字符都去掉。 第三行表示將字符串中的重復的且重復字符在0-9字符集中的字符去掉,這里沒有。 如果我們想要去掉空行,可以這樣操作: tr -s "\n" < inputfile 或者 tr -s "\012" <inputfile // 這兩個是一樣的。 就是將重復的換行符去掉,只留一個。 六,刪除字符 -d選項和-s選項類似,只不過-d選項會刪除所有出現的字符。 [root@kevin ~]# echo "hello world,root" | tr -d "a-h" llo worl,root [root@kevin ~]# echo "hello world,root,2012" | tr -d "a-z" ,,2012 [root@kevin ~]# echo "hello world,root,2012" | tr -d "0-9"
sort/uniq/cut/wc命令
sort 命令對 File 參數指定的文件中的行排序,並將結果寫到標准輸出。如果 File 參數指定多個文件,那么 sort 命令將這些文件連接起來,並當作一個文件進行排序。
sort語法
sort [-fbMnrtuk] [file or stdin]
選項與參數:
-f :忽略大小寫的差異,例如 A 與 a 視為編碼相同;
-b :忽略最前面的空格符部分;
-M :以月份的名字來排序,例如 JAN, DEC 等等的排序方法;
-n :使用『純數字』進行排序(默認是以文字型態來排序的);
-r :反向排序;
-u :就是 uniq ,相同的數據中,僅出現一行代表;
-t :分隔符,默認是用 [tab] 鍵來分隔;
-k :以那個區間 (field) 來進行排序的意思
對/etc/passwd 的賬號進行排序
[root@kevin ~]# cat /etc/passwd | sort
adm:x:3:4:adm:/var/adm:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
sort 是默認以第一個數據來排序,而且默認是以字符串形式來排序,所以由字母 a 開始升序排序。
/etc/passwd 內容是以 : 來分隔的,我想以第三欄來排序,該如何
[root@kevin ~]# cat /etc/passwd | sort -t ':' -k 3
root:x:0:0:root:/root:/bin/bash
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
默認是以字符串來排序的,如果想要使用數字排序:
[root@kevin ~]# cat /etc/passwd | sort -t ':' -k 3n
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
默認是升序排序,如果要倒序排序,如下
[root@kevin ~]# cat /etc/passwd | sort -t ':' -k 3nr
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
ntp:x:106:113::/home/ntp:/bin/false
messagebus:x:105:109::/var/run/dbus:/bin/false
sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin
如果要對/etc/passwd,先以第六個域的第2個字符到第4個字符進行正向排序,再基於第一個域進行反向排序。
[root@kevin ~]# cat /etc/passwd | sort -t':' -k 6.2,6.4 -k 1r
sync:x:4:65534:sync:/bin:/bin/sync
proxy:x:13:13:proxy:/bin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
查看/etc/passwd有多少個shell:對/etc/passwd的第七個域進行排序,然后去重:
[root@kevin ~]# cat /etc/passwd | sort -t':' -k 7 -u
root:x:0:0:root:/root:/bin/bash
syslog:x:101:102::/home/syslog:/bin/false
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin
==================================================================
uniq命令可以去除排序過的文件中的重復行,因此uniq經常和sort合用。也就是說,為了使uniq起作用,所有的重復行必須是相鄰的。
uniq語法
uniq [-icu]
選項與參數:
-i :忽略大小寫字符的不同;
-c :進行計數
-u :只顯示唯一的行
[root@kevin ~]# cat testfile
hello
world
friend
hello
world
hello
直接刪除未經排序的文件,將會發現沒有任何行被刪除
[root@kevin ~]# uniq testfile
hello
world
friend
hello
world
hello
排序文件,默認是去重
[root@kevin ~]# cat words | sort |uniq
friend
hello
world
排序之后刪除了重復行,同時在行首位置輸出該行重復的次數
[root@kevin ~]# sort testfile | uniq -c
1 friend
3 hello
2 world
僅顯示存在重復的行,並在行首顯示該行重復的次數
[root@kevin ~]# sort testfile | uniq -dc
3 hello
2 world
僅顯示不重復的行
[root@kevin ~]# sort testfile | uniq -u
friend
===============================================
sort|uniq 排序去重
sort|uniq -c|srot -rn 排序去重,並降序
sort|uniq -c 打印重復的行數
sort|uniq -d 打印交集部分
sort|uniq -u 打印交集以外的部分
==============================================
[root@kevin ~]# cat a.txt
sdfsdf
123
123
1234
123
dasdfsd
sdfsdf
asfd34234
[root@kevin ~]# cat a.txt |sort|uniq
123
1234
asfd34234
dasdfsd
sdfsdf
[root@kevin ~]# cat a.txt |sort|uniq -c
3 123
1 1234
1 asfd34234
1 dasdfsd
2 sdfsdf
[root@kevin ~]# cat a.txt |sort|uniq -d
123
sdfsdf
[root@kevin ~]# cat a.txt |sort|uniq -u
1234
asfd34234
dasdfsd
[root@kevin ~]# cat a.txt
sdfsdf
123
123
1234
123
dasdfsd
sdfsdf
asfd34234
[root@kevin ~]# cat b.txt
sdf
123
err
2345
123
gggg
[root@kevin ~]# cat a.txt b.txt |sort|uniq
123
1234
2345
asfd34234
dasdfsd
err
gggg
sdf
sdfsdf
[root@kevin ~]# cat a.txt b.txt |sort|uniq -c
5 123
1 1234
1 2345
1 asfd34234
1 dasdfsd
1 err
1 gggg
1 sdf
2 sdfsdf
[root@kevin ~]# cat a.txt b.txt |sort|uniq -d
123
sdfsdf
[root@kevin ~]# cat a.txt b.txt |sort|uniq -u
1234
2345
asfd34234
dasdfsd
err
gggg
sdf
=======================================================
cut命令可以從一個文本文件或者文本流中提取文本列。
cut語法
cut -d'分隔字符' -f fields <==用於有特定分隔字符
cut -c 字符區間 <==用於排列整齊的信息
選項與參數:
-d :后面接分隔字符。與 -f 一起使用;
-f :依據 -d 的分隔字符將一段信息分割成為數段,用 -f 取出第幾段的意思;
-c :以字符 (characters) 的單位取出固定字符區間;
PATH 變量如下
[root@kevin ~]# echo $PATH
/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/X11R6/bin:/usr/games
# 1 | 2 | 3 | 4 | 5 | 6 | 7
將 PATH 變量取出,我要找出第五個路徑。
[root@kevin ~]# echo $PATH | cut -d ':' -f 5
/usr/local/bin
將 PATH 變量取出,我要找出第三和第五個路徑。
[root@kevin ~]# echo $PATH | cut -d ':' -f 3,5
/sbin:/usr/local/bin
將 PATH 變量取出,我要找出第三到最后一個路徑。
[root@kevin ~]# echo $PATH | cut -d ':' -f 3-
/sbin:/usr/sbin:/usr/local/bin:/usr/X11R6/bin:/usr/games
將PATH 變量取出,我要找出第一到第三個路徑。
[root@kevin ~]# echo $PATH | cut -d ':' -f 1-3
/bin:/usr/bin:/sbin:
將PATH 變量取出,我要找出第一到第三,還有第五個路徑。
[root@kevin ~]# echo $PATH | cut -d ':' -f 1-3,5
/bin:/usr/bin:/sbin:/usr/local/bin
實用例子:只顯示/etc/passwd的用戶和shell
[root@kevin ~]# cat /etc/passwd | cut -d ':' -f 1,7
root:/bin/bash
daemon:/bin/sh
bin:/bin/sh
====================================================
wc
統計文件里面有多少單詞,多少行,多少字符。
wc語法
[root@kevin ~]# wc [-lwm]
選項與參數:
-l :僅列出行;
-w :僅列出多少字(英文單字);
-m :多少字符;
默認使用wc統計/etc/passwd
[root@kevin ~]# wc /etc/passwd
40 45 1719 /etc/passwd
40是行數,45是單詞數,1719是字節數
wc的命令比較簡單使用,每個參數使用如下:
[root@kevin ~]# wc -l /etc/passwd #統計行數,在對記錄數時,很常用
40 /etc/passwd #表示系統有40個賬戶
[root@kevin ~]# wc -w /etc/passwd #統計單詞出現次數
45 /etc/passwd
[root@kevin ~]# wc -m /etc/passwd #統計文件的字節數
1719
split命令:切分文件
split命令用於將一個文件分割成數個。 該指令將大文件分割成較小的文件,在默認情況下將按照每1000行切割成一個小文件。 語法 split [--help][--version][-<行數>][-b <字節>][-C <字節>][-l <行數>][要切割的文件][輸出文件名] 參數說明: -<行數> : 指定每多少行切成一個小文件.如split -3 a.txt -b<字節> : 指定每多少字節切成一個小文件 -l, --lines=NUMBER:對file進行切分,每個文件有NUMBER行。 --help : 在線幫助 --version : 顯示版本信息 -C<字節> : 與參數"-b"相似,但是在切 割時將盡量維持每行的完整性 [輸出文件名] : 設置切割后文件的前置文件名, split會自動在前置文件名后再加上編號 示例1: 使用指令split將文件a.txt每3行切割成一個文件,輸入如下命令: 注意:是按照a.txt文件中的行數進行分割的,每3行切分到一個文件中,切割成多個以"x"開頭的小文件。直至所有行數被分完。 [root@kevin ~]# cat a.txt sdfsdf 123123123 sdfasdf2r345345 kljljkl sjkdfjsdofopf sadfsd2343 123123 asdf4555 66666 888888 [root@kevin ~]# split -3 a.txt [root@kevin ~]# ls anaconda-ks.cfg a.txt xaa xab xac xad [root@kevin ~]# cat xaa sdfsdf 123123123 sdfasdf2r345345 [root@kevin ~]# cat xab kljljkl sjkdfjsdofopf sadfsd2343 [root@kevin ~]# cat xac 123123 asdf4555 66666 [root@kevin ~]# cat xad 888888 示例2: 有個文件要處理,因為很大,所以想把它切成若干份,每份N行,以便並行處理。 參數說明: -b, --bytes=SIZE:對file進行切分,每個小文件大小為SIZE。可以指定單位b,k,m。 -l, --lines=NUMBER:對file進行切分,每個文件有NUMBER行。 prefix:分割后產生的文件名前綴。 示例: 假設要切分的文件為test.2012-08-16_17,大小1.2M,12081行。 1) [root@kevin ~]# split -l 5000 test.2012-08-16_17 生成xaa,xab,xac三個文件。 [root@kevin ~]# wc -l #看到三個文件行數如下: 5000 xaa 5000 xab 2081 xac 12081 總計 2) [root@kevin ~]# split -b 600k test.2012-08-16_17 生成xaa,xab兩個文件 [root@kevin ~]# ls -lh #看到兩個文件大小如下: 600K xaa 554K xab 3) [root@kevin ~]# split -b 500k test.2012-08-16_17 example 得到三個文件,文件名的前綴都是example [root@kevin ~]# ls -lh #看到文件信息如下: 500K exampleaa 500K exampleab 154K exampleac 示例3: 將一個大文件分成若干個小文件方法 例如將一個BLM.txt文件分成前綴為 BLM_ 的1000個小文件,后綴為系數形式,且后綴為4位數字形式 [root@kevin ~]# wc -l BLM.txt #讀出 BLM.txt 文件一共有多少行 [root@kevin ~]# split -l 2482 ../BLM/BLM.txt -d -a 4 BLM_ 將文件 BLM.txt 分成若干個小文件,每個文件2482行(-l 2482),文件前綴為BLM_ ,系數不是字母而是數字(-d),后綴系數為四位數(-a 4) ===================================================== Linux下文件分割可以通過split命令來實現,可以指定按行數分割和安大小分割兩種模式。Linux下文件合並可以通過cat命令來實現,非常簡單。 在Linux下用split進行文件分割: 模式一:指定分割后文件行數 對與txt文本文件,可以通過指定分割后文件的行數來進行文件分割。 命令:split -l 300 large_file.txt new_file_prefix 模式二:指定分割后文件大小 split -b 10m server.log waynelog 對二進制文件我們同樣也可以按文件大小來分隔。 在Linux下用cat進行文件合並: 命令:cat small_files* > large_file 將a.txt的內容輸入到b.txt的末尾 cat a.txt >> b.txt
comm命令:對於兩個已排序文件,逐行比對
一、常用用法
comm FILE1 FILE2
二、含義與選項
2.1、含義
對於兩個已排序的文件,逐行比對。
打印結果有3列:第1列,只屬於“FILE1”的行;第2列,只屬於“FILE2”的行;第3列,既屬於“FILE1”,又屬於“FILE2”的行。
2.2、選項表示的意思
“FILE1,FILE2”:指代已排序文件“FILE1”和“FILE2”
三、其他
3.1、“LC_COLLATE”等環境變量
由於涉及到兩個字符串的比較等,故而程序實現中使用“LC_COLLATE”等環境變量,最終結果受到“LC_COLLATE”等環境變量的控制。
3.2、排序策略
comm命令實現設定的排序策略是“按照字典序排序”。兩個已排序文件使用的排序策略組合共有3種情況。
3.2.1、情況1
一個排序文件按照字典序排序,另外一個排序文件按照非字典序(其他排序策略)排序。顯而易見,在這種情況下,comm命令的執行結果會比較奇怪。
[root@localhost ~]# cat a.txt
001
02
3
10
[root@localhost ~]# cat b.txt
001
02
5
06
007
10
即已按照“數值大小”排序,執行“逐行比對”過程,我們的預期結果是:“3”只屬於“c.txt”,“5,06,007”只屬於“d.txt”,“001,02,10”共屬於兩個文件。
現在執行comm a.txt b.txt命令,得到如圖1所示結果,不能達到預期。
[root@localhost ~]# comm a.txt b.txt
001
02
3
comm: file 1 is not in sorted order
10
5
comm: file 2 is not in sorted order
06
007
10
執行comm --nocheck-order a.txt b.txt命令,得到如圖2所示結果,也不能達到預期。
[root@localhost ~]# comm --nocheck-order a.txt b.txt
001
02
3
10
5
06
007
10
兩個文件都已按照字典序排序,這符合comm命令實現的設定,comm命令的執行結果能夠達到預期。執行下述命令,得到如圖3所示結果,結果符合預期。
[root@localhost ~]# sort a.txt > aa.txt
[root@localhost ~]# sort b.txt > bb.txt
[root@localhost ~]# comm aa.txt bb.txt
001
007
02
06
10
3
5
[root@localhost ~]# cat aa.txt
001
02
10
3
[root@localhost ~]# cat bb.txt
001
007
02
06
10
5
join命令:根據兩行中具有相同值的兩個字段,將該兩行內容拼接成一行打印輸出
一、常用用法 join [-t CHAR] [-i] [--header] [-1 FIELD] [-2 FIELD] [-e STR] FILE1 FILE2 二、含義與選項 2.1、含義 存在兩個已排序文件,假如文件1中的某條記錄的某個字段值(默認是第一個字段,從1開始計數)與文件2中的某條記錄的某個字段值 (默認是第一個字段,從1開始計數)一致,那么在最終打印結果中,將這兩條記錄拼接成一條記錄。 2.2、選項表示的意思 “-t CHAR”:以“CHAR”字符作為記錄內字段間的分隔符,默認的分隔符是“空格符” “-i”:兩個字段值比較時,忽略大小寫 “–header”:兩個文件的第一行作為說明行,不參與比較 “-1 FIELD”:FILE1中以第“FIELD”個字段作為比較字段 “-2 FIELD”:FILE2中以第“FIELD”個字段作為比較字段 “-e STR”:在最終的拼接記錄中,如果某個字段的值為空,那么以“STR”替換 “FILE1”:文件1 “FILE2”:文件2 示例一 有文件“a.txt”和“b.txt”,內容分別如下: [root@localhost ~]# cat a.txt a 1 b 2 [root@localhost ~]# cat b.txt a 3 b 4 執行以下命令,得到如下結果: [root@localhost ~]# join a.txt b.txt a 1 3 b 2 4 示例二 有文件“a.txt”和“b.txt”,內容分別如下: [root@localhost ~]# cat a.txt a;1 b;2 [root@localhost ~]# cat b.txt a;3 b;4 執行以下命令,得到如下結果: [root@localhost ~]# join -t ';' a.txt b.txt a;1;3 b;2;4 示例三 有文件“a.txt”和“b.txt”,內容分別如下: [root@localhost ~]# cat a.txt A 1 b 2 [root@localhost ~]# cat b.txt a 3 b 4 執行以下命令,得到如下結果: [root@localhost ~]# join -i a.txt b.txt A 1 3 b 2 4 示例四 有文件“a.txt”和“b.txt”,內容分別如下: [root@localhost ~]# cat a.txt Col1 Col2 a 1 b 2 [root@localhost ~]# cat b.txt Col3 Col4 a 3 b 4 執行以下命令,得到如下結果: [root@localhost ~]# join --header a.txt b.txt Col1 Col2 Col4 a 1 3 b 2 4 示例五 有文件“a.txt”和“b.txt”,內容分別如下: [root@localhost ~]# cat a.txt a 1 f b 2 g [root@localhost ~]# cat b.txt f 3 5 g 4 6 執行以下命令,得到如下結果: [root@localhost ~]# join -1 3 -2 1 a.txt b.txt f a 1 3 5 g b 2 4 6 示例六 有文件“a.txt”和“b.txt”,內容分別如下: [root@localhost ~]# cat a.txt a b 2 [root@localhost ~]# cat b.txt a 3 b 4 執行以下命令,得到如下結果: [root@localhost ~]# join -e "hello world" a.txt b.txt a hello world 3 b 2 4 四、其他 4.1、“LC_COLLATE”等環境變量 由於涉及到兩個字符串的比較等,故而程序實現中使用“LC_COLLATE”等環境變量,最終結果受到“LC_COLLATE”等環境變量的控制。 4.2、排序策略 跟“comm”命令一樣,join命令實現設定的排序策略是“按照字典序排序”。因而,兩個文件“已排序”應該是按照字典序已排序,否則執行join命令得到的結果很有可能不能符合預期。
