文件文本過濾與vim

文本主要介紹正則表達式、grep家族命令,以及vim與文件查找工具,如find與locate。

一、正則表達式

0. 概念

正則表達式(REGular EXPression,REGEXP)使用單個字符串來描述、匹配一系列匹配某個句法規則的字符串的機制。它將一些字符作爲元字符(Meta Characteristic) 用於標識一類字符或用於特殊限定,而不是標識其原有的字面意義。

在進行文本匹配時,我們所寫的匹配表達式被稱爲模式(Pattern) ,而在Linux中,最常用的支持正則表達式的程序爲grep家族程序,根據其劃分,又分爲:

  • BRE(Basic RegEx),基本正則表達式
  • ERE(Extended RegEx),擴展正則表達式

在介紹正則表達式之前,前介紹grep的用法

1. grep、egrep、fgrep

這三個命令類似,都用作文本過濾,grep(Global Search Regular EXpression and print out the line)默認使用BRE,egrep默認使用ERE,fgrep模式不支持REGEXP,f爲fast之意。

由於以上三個命令可以使用參數而達到與彼此相同的效果,故而此處以grep爲例進行說明,其用法如下:

grep [OPTIONS] PATTERN [FILE...]
	[OPTIONS]
		-i			ignore-case 忽略大小寫
		--colour=auto
				將匹配到的字符高亮顯示,默認命令別名開啓
		-v			反向匹配,顯示沒有被模式匹配到的行
		-o			只顯示被模式匹配到的字符串,而非整行
		-q			靜默模式,不輸出任何信息
		-E			支持擴展的正則表達式(egrep)
		-F			支持快速匹配(fgrep)
		-A #		After,顯示被模式匹配到的後面的#行
		-B #		Before,顯示被模式匹配到的前面的#行
		-C #		Context,顯示被模式匹配到的前#行與後#行
		-P			使用perl風格的正則表達式

	PATTERN
		模式,即用於匹配的條件,將在下面介紹

2. 基本正則表達式(BRE)

Globbing回顧

通配符 意義
* 任意長度的任意字符
? 任意單個字符
[] 指定範圍內的任意單個字符
[^] 指定範圍外的任意單個字符

BRE元字符

正則表達式的介紹主要內容爲介紹其元字符,分爲以下幾類:

  • 字符匹配
  • 次數匹配
  • 位置錨定
  • 分組

字符匹配

元字符 意義
. 匹配任意字符
[] 匹配指定範圍內的字符
[^] 匹配指定範圍外的字符

注意,這裏只是確定匹配什麼字符,匹配次數並不由此限制。

關於範圍,可使用如下方式表示:

範圍 意義
[0-9],[[:digit:] 數字
[a-z],[[:lower:]] 小寫字母
[A-Z],[[:upper:]] 大寫字母
[[:punct:]] 標點符號
[[:space:]] 空白符號
[[:alpha:]] 所有字母(大寫與小寫)
[[:alnum:]] 字母與數字

以上兩個中括號的意義爲,外層標識正則表達式的範圍,內層與其中的內容共同標識一個集合,若要匹配外圍以外的,組在兩個中括號之間加上^即可,如:

[^[:lower:]]:非小寫字母

匹配次數

用在要指定其出現的次數的字符的後面,用於限定其前面字符出現的次數

元字符 意義
* 匹配其前面字符任意次(0次,1次,或多次)
\? 0次或1次
\+ 1次或多次
\{m\} m次
\{m,n\} 至少m次,至多n次

這裏需要使用轉義,因爲BRE將+、?、{、}等字符默認是作爲字字面意義進行匹配的,這裏需要使其作爲元字符使用。

另外,關於次數匹配也有以下用法:

次數表示 意義
.* 任意長度的任意字符
\{0,n\} 至多n次
\{m,\} 至少m次
貪婪模式

試想若有如下內容的文本:

one two one three one

使用以下命令進行匹配:

grep -o "one.*one" test.grep

得到的結果爲:

one two one three one

而事實上“one two one”也是滿足模式的,這裏之所以是如此結果,是因爲grep默認工作在 貪婪模式 下,這意味着grep會儘可能長地匹配字符。

若要儘可能短地匹配,則需要其在非貪婪模式下匹配,而grep與egrep默認是不支持這種模式的。

我們可以使用-P選項,以爲使用Perl語言風格的正則表達式進行模式匹配,號稱Perl的正則表達式引擎是非常強大的。

Perl風格中,在次數限定元字符後加 ? 可使其工作在非貪婪模式下,如:

grep -o -P "one.*?one" test.grep

結果爲

one two one

位置錨定

元字符 意義
^ 錨定行首
$ 錨定行尾
\<或\b 錨定詞首,用於單詞左側
\>或\b 錨定詞尾,用於單詞右側

常見用法

模式 意義
\<PATTERN\> 匹配完整單詞
^PATTERN$ 用PATTERN匹配整行
^$ 空白行
^[[:space:]]*$ 空行或包含空白字符的行

分組與引用

有時需要將一個組合作爲一個單位進行限定,如要匹配出現多個連續的“ab”,此時可使用分組

分組是使用小括號實現的,不過在BRE中需要轉義,如以上要求的模式應寫爲\(ab\)*

分組的另一個作用爲,可再次引用匹配到的內容(後向引用),如若使用r..t匹配到了“root”,則在下次引用時,引用的佔位符將被替換爲“root”。

分組括號中的模式匹配到的內容會被正則表達式引擎記錄於內部變量中,這些變量的命名方式爲\1,\2,\3,……

如,有以下文本內容:

He likes his lover.
She loves her liker.
He loves his lover.
She likes her liker.

grep '\(l..e\).*\1r'將會匹配到:

He loves his lover.
She likes her liker.

  • 顯示/proc/meminfo文件中以不區分大小的s開頭的行;
    grep -i '^s' /proc/meminfo
    grep '^[sS]' /proc/meminfo
    
  • 顯示/etc/passwd中以nologin結尾的行;
    grep 'nologin$' /etc/passwd
    
  • 取出默認shell爲/sbin/nologin的用戶列表
    grep "nologin$' /etc/passwd | cut -d: -f1
    
  • 取出默認shell爲bash,且其用戶ID號最小的用戶的用戶名
    grep 'bash$' /etc/passwd | sort -n -t: -k3 | head -1 | cut -d: -f1
    
  • 顯示/etc/inittab中以#開頭,且後面跟一個或多個空白字符,而後又跟了任意非空白字符的行;
    grep "^#[[:space:]]\{1,\}[^[:space:]]" /etc/inittab
    
  • 顯示/etc/inittab中包含了:一個數字:(即兩個冒號中間一個數字)的行;
    grep ':[0-9]:' /etc/inittab
    
  • 顯示/boot/grub/grub.conf文件中以一個或多個空白字符開頭的行;
    grep '^[[:space:]]\{1,\}' /boot/grub/grub.conf
    
  • 顯示/etc/inittab文件中以一個數字開頭並以一個與開頭數字相同的數字結尾的行;
    grep '^\([0-9]\).*\1$' /etc/inittab
    
  • 找出"netstat -tan"命令的結果中以’LISTEN’後跟0、1或多個空白字符結尾的行;
    netstat -tan | grep "LISTEN[[:space:]]*$"
    

3. 擴展正則表達式(ERE)

ERE與BRE類似,只是將更多的字符納入了元字符,如此在使用時將不必轉義,其他與BRE類似,與這裏做如下總結

字符匹配

元字符 意義
. 匹配任意字符
[] 匹配指定範圍內的字符
[^] 匹配指定範圍外的字符

匹配次數

元字符 意義
* 匹配其前面字符任意次(0次,1次,或多次)
? 0次或1次
+ 1次或多次
{m} m次
{m,n} 至少m次,至多n次

位置錨定

元字符 意義
^ 錨定行首
$ 錨定行尾
\<或\b 錨定詞首,用於單詞左側
\>或\b 錨定詞尾,用於單詞右側

分組與引用

元字符 意義
() 分組
\1, \2, \3, … 後向引用

或者

元字符 意義
| 表示“或者”之意

該元字符在BRE中並未出現,這裏需要說明的是,|匹配的是真個左邊或整個右邊,而不是單個字符,如:
c|Cat可以匹配的是c與Cat,而非cat與Cat,若要用C|cat表示C|c可以使用()分組:(C|c)at

二、vim

1. 介紹

同nano一樣,vim也是一款全屏幕的編輯器,他是vi(visual Interface)編輯器的進化版(improved),功能異常強大。

vim是一個模式化的編輯器,這裏介紹常用幾種模式

  • 編輯模式:默認處於該模式下,在該模式中,鍵盤操作通常被解釋爲編輯命令而非輸入字符
  • 輸入模式:該模式下鍵盤的輸入將被錄入到屏幕
  • 末行模式:即命令行模式,可在此進行復雜的操作
  • 可視化模式:便於快捷查看、選定等

其界面如下:
vim界面

2. 常用參數

vim [OPTIONS] /PATH/TO/SOMEFILE...
	OPTIONS
		-o			水平分割顯示
		-O			垂直分割顯示
			Ctrl+w,箭頭	窗口間跳轉
			若打開單個文件,這裏將不會分隔窗口
		
		+N				打開文件並定位在第N行的行首
		+/PATTERN		打開文件後,直接讓光標處於第一個被PATTERN匹配到的行的行首
		+				打開文件並定位在最後一行

3. 模式間轉換

編輯模式–>輸入模式
i:insert,在當前光標所在字符的前面,轉換爲輸入模式
a:append,在當前光標所在字符的後面,轉換爲輸入模式
o:在當前光標所在行的下方,新建一行,並轉爲輸入模式
I:在當前光標所在行的行首,轉換爲輸入模式
A:在當前光標所在行的行尾,轉換爲輸入模式
O:在當前光標所在行的上方,新建一行,並轉換爲輸入模式
輸入模式–>編輯模式
ESC鍵
編輯模式–>末行模式
:
末行模式–>編輯模式
ESC
命令行有內容時可敲擊多次ESC
編輯模式–>可視化模式
v

4. 常用通配符

通配符 意義
. 當前行
$ 最後一行
$-1 倒數第二行
+# 向下的#行

5. 編輯模式

移動光標

逐字符移動

按鍵 動作
h或← 向左
l或→ 向右
j或↓ 向下
k或↑ 向上
#COMMAND:可以移動#個字符如:
4l:向右移動4字符
6←:向左移動6字符

以單詞爲單位移動

按鍵 動作
w 移至下一個單詞的詞首
b 調至當前或前一個單詞詞首
e 跳至當前或下一個單詞詞尾

#COMMAND:可以移動#個單詞

行內跳轉

按鍵 動作
0 數字0,跳至絕對行首
^ 跳至行首的第一個非空白字符
$ 跳至絕對行尾

行間跳轉

按鍵 動作
#G 跳轉至第#行
G 跳轉至最後一行
1G或gg 跳轉至第一行

句子間跳轉

按鍵 動作
) 下一句
( 上一句

段落間跳轉

按鍵 動作
} 下一段
{ 上一段

翻屏

按鍵 動作
Ctrl+f 向文件尾部翻一屏
Ctrl+b 向文件首部翻一屏
Ctrl+d 向文件尾部翻半屏
Ctrl+u 向文件首部翻半屏
Enter 按行向後翻

刪除單個字符

按鍵 動作
x 刪除光標所在處的單個字符
#x 刪除光標所在處及向後的共#個字符

刪除命令:d

d命令跟跳轉命令組合使用,用於刪除光標當前位置到跳轉到位置的字符,#d跳轉符:如:

按鍵 動作
3dw 刪除光標向後的3個單詞
d^ 刪除至行首
d$ 刪除至行尾
dd 刪除當前光標所在行
#dd 刪除包括當前光標所在行在內的下#行

修改命令:c

即先刪除內容,再轉換爲輸入模式,用法同d命令,如

按鍵 動作
c$ 刪除光標值行尾內容並轉爲輸入模式
c^ 刪除光標值行首內容並轉爲輸入模式
cc 刪除光標所在行內容並轉爲輸入模式
#cc 刪除包括當前光標所在行在內的下#行並轉爲輸入模式

複製命令:y

使用方法同刪除命令,如

按鍵 動作
c$ 複製光標值行尾內容
c^ 複製光標值行首內容
cc 複製光標所在行內容
#cc 複製包括當前光標所在行在內的下#行

粘貼命令:p

vim中編輯的內容可以撤銷,最後一次刪除的內容會被保存至內存的緩衝區中,可以用於下次粘貼至他處,相當於剪切

p(小寫)
如果刪除或複製的內容爲整行內容,則粘貼至光標所在行的下方;
如果刪除或複製的內容爲非整行,則粘貼至光標所在字符的後面;
P(大寫)
如果刪除或複製的內容爲整行內容,則粘貼至光標所在行的上方;
如果刪除或複製的內容爲非整行,則粘貼至光標所在字符的前面

替換命令:r

先按r,再按下字符,可以將當前光標所在的字符替換的鍵入的字符

#r:向後替換#個字符

可敲R進入替換模式,替換模式下鍵入的字符將直接替換原字符

撤銷

按鍵 動作
u 撤銷前一次的編輯操作
#u 撤消指定次數的操作
U 僅撤銷光標所在行的編輯操作
Ctrl+r 還原撤銷

連續u命令可撤消此前的n次編輯操作,默認最多撤銷50次操作

重複之前的操作

在編輯模式中,使用.可重複之前的操作

分屏顯示

按鍵 動作
Ctrl+w, s 水平拆分窗口
Ctrl+w, v 垂直拆分窗口

在窗口鍵切換的方式爲:Ctrl+w,箭頭

關閉文件

ZZ (大寫)保存並退出

6. 可視化模式

該模式可以選中光標劃過的所有字符

按鍵 動作
v 按字符選取
V 按行選取

經常結合編輯命令:d,c,y

7. 末行模式

打開文件

按鍵 動作
:e FILE 打開新文件
:r FILE 讀取其他文件至當前文件

關閉文件

按鍵 動作
:q 不保存退出(若修改了文件內容則無法退出)
:wq 保存並退出
:x 同: wq ,保存並退出
:q! 強行不保存退出
:w 保存(只讀屬性的文件無法保存)
:w /PATH/TO/SOMEFILE 另存爲
:w! 強行保存(管理員)
qall 退出所有文件
wall 保存所有文件

移動光標

直接給出行號,回車即可

地址定界

使用地址定界的形式爲:START,END,如

定界操作 意義
# 第#行
m,n 第m行到第n行
m,+n 相對定界,從第m行開始,往後n行
. 當前行
$ 最後一行
$-2 倒數第3行
/PAT1/,/PAT2/ 自光標處開始匹配,從第一次能夠被模式一(PAT1)匹配到的行開始,到以第一次能夠被模式二(PAT2)匹配到的行結束,中間的所有行,通常的使用形式爲/PAT/,$
% 全文,相當於1,$

編輯操作

末行模式中的編輯操作格式爲:地址定界後跟一個編輯命令,可實現對範圍內的內容進行相應的編輯操作。如:

指令 操作
#d 刪除光標所在行與向下的行供#行
%y 複製全部內容
m,nw /PATH/TO/SOMEWHERE 將m行到n行的內容寫入指定文件中
m,nr /PATH/FROM/SOMEFILE 將m至n行的內容替換爲指定文件中的內容

查找

指令 操作
/PATTERN 從當前光標向尾部查找
?PATTERN 從當前光標向首部查找
n 與命令同方向
N 與命令反方向

查找並替換:s

在末行模式下使用s命令,用法同sed中的s命令1

s命令默認只替換每行中第一次被模式匹配到的字符串,其使用格式爲:

:地址定界s/查找模式/替換爲的內容/修飾符
分隔符
/爲分隔符,可以換成其他字符,如s### s@@@ …
緊跟在s之後的字符,會被解析成定界符
若pattern中或string中有與分隔符相同的,使用\轉義
查找模式
這裏的模式支持正則表達式
替換爲的內容
替換爲的內容不支持正則表達式,但可以使用\1, \2, … 等後向引用,還可以使用&引用前面查找時查找到的整個內容
修飾符
修飾符 意義
g global,全局替換,替換(一行中)所有被模式匹配到的字符串,默認只替換每一行的第一個
i ignore-case,忽略字符大小寫

如:

  • 刪除全文的行首的#
    :%s@^#@@g

  • 將1到30行行首是非#的行加上#
    :1,30s@^[^#]@#&@g

  • 將行首的空白字符替換爲空
    :%s/^[[:space:]]\+//

  • 將每行開頭爲空白符的行首加一個#
    :%s/^[[:space:]]/#&/

分屏顯示

按鍵 動作
:sp [FILE] 水平分割顯示
:vsp [FILE] 垂直分割顯示

文件間切換

當使用vim同時打開多個文件而沒有指定分屏時,默認是將第一個文件全屏顯示的,此時可以通過如下方式在打開的文件之間切換:

指令 操作
: next 切換至下一個文件
: previous 切換至前一個文件
: last 切換至最後一個文件
: first 切換至第一個文件

與shell交互

即在vim中執行shell命令,在末行模式下輸入!,後跟命令即可。

若在vim中編輯了內容,在未保存的情況下意外關閉,在下次編輯時vim將會警告,可以使用vim -r 恢復未保存的數據,刪除同目錄下的*.swp文件,亦可在警告窗口中根據提示進行操作

8. 定製vim的工作特性

在末行模式下使用set可設定相關參數,用於修改vim的當前配置,不帶任何參數的set命令可查看set的幫助

顯示或取消顯示行號

: set number			顯示行號
: set nu

: set nonumber			取消顯示
: set nonu

設定忽略或區分字符大小寫

: set ignorecase			忽略大小寫
: set ic

: set noic					區分大小寫

設定自動縮進

: set autoindent		自動縮進
: set ai

: set autoindent		取消縮進
: set noai

高亮搜索

: sethlsearch			高亮顯示搜索到的文本
: set nohlsearch		取消高亮顯示搜索到的文本
: nohl					取消高亮顯示搜索到的文本

語法高亮

: syntax on		開啓語法着色
: syntax off		關閉語法着色

高亮顯示與之匹配的括號

:setshowmatch		顯示與之匹配的括號
:set sm			

:setshowmatch		取消顯示
:set nosm

該操作可立即生效,作用域僅爲當前vim進程

9. vim的配置文件

vim有兩種配置文件

  • /etc/vimrc:對所有用戶生效
  • ~/.vimrc:僅對當前用戶生效,若不存在,可自行創建

通過將以上屬性設置指令寫入配置文件,可永久生效

10. 獲取幫助

vim是一個很複雜的工具,這裏介紹的只是基礎用法,關於幫助的獲取,可使用如下方式:

  • : help:在末行模式下輸入help和查看vim的幫助
  • : help SUBJECT:help後跟一個關鍵字可查看該部分幫助

另外,vimtutor命令中有關於vim的相關教程

三、文件查找

前文介紹的grep家族工具用作文本過濾,他們作用於文件時,是過濾文件內容,而此處介紹的文件查找工具,將通過特定條件,查找文件本身。

locate

該命令將通過文件名查找文件,基本使用格式爲:

locate [OPTION]... PATTERN…
	[OPTION]
		-b:只匹配基名
		-c:統計出共有多少個符合條件的文件
		-r:基於BRE(基本正則表達式)搜索

需要說明的是,find的查找是根據全系統數據庫進行的,系統將在任務計劃的配置下,在設定時間將系統上的文件信息收集到全系統數據庫中,locate將在這個數據庫中進行查找,速度較快,但由於是基於該索引,故其結果並非實時。

如當前新建了一個文件,呃索引數據尚未建立該條目,則locate將無法找到該文件,欲手動生成文件數據庫,可使用updatedb命令構建索引
注意,索引構建過程需要遍歷整個根文件系統,極其消耗資源

find

與locate不同,find命令將做實時查找,並且支持衆多查找標準,因而其速度較find慢

其使用格式爲:

find [option] …  [查找路徑] [查找條件] [處理操作]
	查找路徑:指定具體目標路徑,默認爲當前目錄
	查找條件:可以是文件名、大小、類型、權限等標準,默認爲指定路徑下的所有文件,即無條件
	處理操作:對符合條件的文件做什麼操作,默認爲輸出至屏幕

以下將對其做詳細說明

查找條件

按文件名

-name 'FILENAME'	對文件名做精確匹配,區分大小寫
	文件名通配
		*			任意長度的任意字符
		?			任意單個字符
		[]			指定範圍內的
		[^]			指定範圍外的

-iname 'FILENAME'	文件名匹配不區分大小寫
-regex 'PATTERN'	基於正則表達式進行文件名匹配
	以PATTERN匹配整個文件路徑字符串,而不僅僅是文件名

按文件歸屬

-user USERNAME		根據屬主查找
-group GRPNAME		根據屬組查找

-uid UID			根據UID查找
-gid GID				根據GID查找
	若一個文件的屬主用戶被刪除,則該文件的屬主將變爲刪除用戶的UID,此時,該文件沒有屬主,屬組亦然

-nouser				查找沒有屬主的文件
-nogroup			查找沒有屬組的文件

按文件類型

-typeTYPE			根據文件類型查找
	f		普通文件
	d		目錄
	c		字符設備文件
	b		塊設備文件
	l		符號鏈接文件
	p		命名管道
	s		套接字文件

按文件大小

-size[+|-]UNIT
	指定查找大小,後跟數字和單位(UNIT),若沒給出單位,則爲默認的“字節”,+和-表示至少、至多

關於單位,可指定爲:

單位 意義
b for 512-byte blocks (this is the default if no suffix is used)
c for bytes
w for two-byte words
k for Kilobytes (units of 1024 bytes)
M for Megabytes (units of 1048576 bytes)
G for Gigabytes (units of 1073741824 bytes)
指定大小查找時,若沒有指定+或-,會匹配在給定大小爲1單位一內的所有文件即
#表示(#-1, #]
-#表示[0, #-1]
+#表示(#, ∞)

按文件時戳

以天爲單位(time)
-mtime [+|-]#			修改時間/天
-ctime [+|-]#			改變時間/天
-atime [+|-]#			訪問時間/天
以分鐘爲單位(min)
-mmin[+|-]#				修改時間/分鐘
-cmin [+|-]#			改變時間/分鐘
-amin [+|-]#			訪問時間/分鐘

+表示#天(或分鐘)以前,-表示#天(或分鐘)以內,以下爲圖示,注意,數軸的方向表示文件某時間戳距此刻的市場,即正方向是指向過去的:
find時間過濾表示方式

按文件權限

-perm MODE:精確匹配
/MODE: 任何一類用戶(u,g,o)的任何一位(r,w,x)權限匹配
	9位權限位
	常用於查找某類用戶的特定權限是否存在

	只判斷一位權限時,+和-一樣
	
-MODE: 每一類用戶都必須同時擁有爲其制定的權限標準

例:

文件權限644
-perm 644 查找文件權限爲644的文件,可以匹配
-perm /222 查找有用戶有寫權限的文件,可以匹配
-perm /002 查找其他用戶有寫權限的文件,不能匹配
-perm -444 可以匹配

條件組合

-a			與(and)
-o			或(or)
-not		非(NOT)
	或!

若給出了多個查找條件而沒有指定邏輯鏈接方式,默認爲與(-a)

處理操作

-print			輸出至標準輸出,默認操作
-ls				類似ls -l 的形式顯示
-delete			刪除查找到的文件

-fls /path/to/somefile
	查找到的文件的長格式信息保存至指定文件中

-exec COMMAND {} \;
	find把查找到的所有文件一次性地傳遞給-exec執行
	執行命令,有些命令不接受過多參數,此時命令執行可能會失敗,此時使用以下方式:
	find | xargs COMMAND
	{}是文件名佔位符,用於引用查找到的文件名自身
	注意:\;前必須有空格,\;二者之間不能都空格
	
-ok COMMAND {} \;		交互式-exec

例:查找/tmp下改變時間爲5分鐘以內的文件,在原文件名之後加上.new

find /tmp -cmin -5 -exec mv {} {}.new \;

不能使用管道將find的結果傳遞給以文件或路徑爲參數的命令來執行,因爲管道傳遞的是路徑,如
find /tmp -perm -003 | chmod o-x是不可以的,因爲chmod需要以文件路徑作爲參數
find /etc -perm -003 | tr 'a-z' 'A-Z'可以,tr本就是處理字符串的命令

可以使用命令替換,如

chmod o-x `find /etc -perm -003`

但是同-exec,都可能出現命令參數溢出,因爲find將找到的內容一次性輸出,解決方式爲:

find | xargs COMMAND

查找文件時,可以將查找到的內容管道送給xargs,執行操作,如

find /etc -perm -003 | xargs chmod o-x
xargs
build and execute command lines from standard input
xargs命令是給其他命令傳遞參數的一個過濾器,也是組合多個命令的一個工具。它擅長將標準輸入數據轉換成命令行參數,xargs能夠處理管道或者stdin並將其轉換成特定命令的命令參數。xargs也可以將單行或多行文本輸入轉換爲其他格式,例如多行變單行,單行變多行。xargs的默認命令是echo,空格是默認定界符。這意味着通過管道傳遞給xargs的輸入將會包含換行和空白,不過通過xargs的處理,換行和空白將被空格取代。xargs是構建單行命令的重要組件之一

使用示例

①查找屬組有寫權限的文件,將其文件名改爲原名後加.new

find ./ -perm -020 -exec mv {} {}.new \;

②查找所有用戶都有執行權限的腳本,將其他用戶的執行權限去掉

find ./ -name "*.sh" -a -perm -111 -exec chmod o-x {} \;

③查找/tmp中沒有屬組或沒有屬主的文件並顯示

find /tmp \( -nouser -o -nogroup \) -ls

④找出/tmp目錄下,屬主不是root,且文件名不是fstab的文件

find /tmp \( -not -user root -a -not -name 'fstab' \) -ls
find /tmp -not \( -user root -o -name 'fstab' \) -ls

⑤查找/etc目錄下最週一周內其內容修改過,同時屬主不爲root,也不是hadoop的文件或目錄

find /etc -mtime -7 -a -not -user root -a -not -user hadoop
find /etc -mtime -7 -a -not \( -user root -o -user hadoop \)

⑥查找/etc目錄下所有用戶都沒有寫權限的文件

find /etc -not -perm /222

⑦查找/etc目錄下至少有一類用戶沒有執行權限的文件

find /etc -not -perm -111

⑧查找/etc/init.d/目錄下,所有用戶都有執行權限且其他用戶有寫權限的文件

find /etc/init.d/ -perm -113
find /etc/init.d/ -perm -111 -o perm +002
find /etc/init.d/ -perm -111 -o perm -002

Tips: 只判斷一位權限時,+和-一樣

四、例

1、定義一個對所有用戶都生效的命令別名,例如:lftps=‘lftp 172.168.0.1/pub’
相關的說明見另一篇文章:https://blog.csdn.net/xiyangyang410/article/details/85454040#bash_51
此處可編輯/etc/bashrc文件,在代碼塊最外層寫入:
alias lftps='lftp 172.168.0.1/pub'
2、顯示/etc/passwd文件中不以/bin/bash結尾的行
使用模式/bin/bash$過濾出以/bin/bash結尾的行,使用grep -v選項取反即可:
[root@localhost ~]# grep -v "/bin/bash$" /etc/passwd
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
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
sssd:x:998:997:User for sssd:/:/sbin/nologin
colord:x:997:995:User for colord:/var/lib/colord:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
libstoragemgmt:x:996:994:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
chrony:x:995:993::/var/lib/chrony:/sbin/nologin
pulse:x:171:171:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
gdm:x:42:42::/var/lib/gdm:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
named:x:25:25:Named:/var/named:/bin/false
gentoo:x:5002:5002:Gentoo Distribution:/home/gentoo:/bin/csh
3、找出/etc/passwd文件中,包含二位數字或者三位數的行
grep ".*[0-9]\{2,3\}.*" /etc/passwd
4、顯示/proc/meminfo文件中以大寫或小寫S開頭的行;用三種方式實現
grep -i "^s" /proc/meminfo			# 使用-i選項忽略大小寫
grep "^[Ss]" /proc/meminfo			# 使用範圍過濾
grep -E "^(S|s)" /proc/meminfo		# 使用擴展正則表達式
5、使用echo輸出一個絕對路徑,使用egrep取出路徑名,類似執行dirname /etc/passwd 的結果
echo /etc/rc.d/init.d/network | egrep -o ".*/"
此方式只能用於文件或目錄後不帶“/”的路徑名,如
[root@localhost ~]# echo /etc/rc.d/init.d/network | egrep -o ".*/"
/etc/rc.d/init.d/
[root@localhost ~]# echo /etc/rc.d/init.d | egrep -o ".*/"
/etc/rc.d/
[root@localhost ~]# echo /etc/rc.d/init.d/ | egrep -o ".*/"
/etc/rc.d/init.d/
暫未想到使用egrep的一個比較好的解決方法,使用sed可進行較好過濾:
echo /etc/rc.d/init.d/network | sed 's@[^/]\{1,\}/\?$@@'
此處使用了sed的查找替換命令s,其餘vim的s相似,關於sed,後續將做詳細介紹
6、找出ifconfig中的ip地址。要求結果只顯示IP地址
以下爲ifconfig的輸出結果:
[root@localhost ~]# ifconfig
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.18.128  netmask 255.255.255.0  broadcast 192.168.18.255
        inet6 fe80::20c:29ff:fecf:6af3  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:cf:6a:f3  txqueuelen 1000  (Ethernet)
        RX packets 24788  bytes 28299954 (26.9 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 10944  bytes 1072371 (1.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 24  bytes 2304 (2.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 24  bytes 2304 (2.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        
ipv4使用點分十進制表示,此處使用的方法爲:
ifconfig | egrep -o '\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[01][0-9]|22[0-3])\>(\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\>){2}\.\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\>'
192.168.18.128
127.0.0.1
7、vim定製自動縮進四個字符
配置自動縮進爲set autoindent,同時修改tab縮進的長度,以及將其自動轉爲空格,將以下內容寫入配置文件中即可:
set autoindent
set tabstop=4
set shiftwidth=4
如上文介紹,將其寫入/etc/vimrc對所有用戶生效,寫入~/.vimrc僅對當前用戶生效
8、編寫腳本,實現自動添加三個用戶,並計算這三個用戶的uid之和
關於腳本編寫運行的基礎介紹,可參考 https://blog.csdn.net/xiyangyang410/article/details/85454040#4__323
此處的實現爲:
#!/bin/bash

# 5: user exits

declare -i sum_uid=0

addusers() {
    if id $1 &> /dev/null; then
        return 5
    else
        useradd $1
        retval=$?
        return $retval
    fi
}

for i in {1..3}; do
    addusers ${1}${i};
    retval=$?
    if [ $retval -eq 0 ]; then
        echo "Add user ${1}${i} finished."
        let sum_uid+=`id -u ${1}${i}`
    elif [ $retval -eq 5 ]; then
        echo "User ${1}${i} exists."
    else
        echo "Unknow error."
    fi
done

echo "The sum of User ID is: $sum_uid."
執行結果:
[root@localhost scripts]# bash useradd-homework.sh user
Add user user1 finished.
Add user user2 finished.
Add user user3 finished.
The sum of User ID is: 15012.
9、find用法以及常用用法的實例演示
見上文

  1. 後續將會介紹sed ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章