99久久全国免费观看_国产一区二区三区四区五区VM_久久www人成免费看片中文_国产高清在线a视频大全_深夜福利www_日韩一级成人av

【工作實踐系列】一些linux命令積累——字符串處理相關(持續更新中)

工作中遇到的數據很多都是按照字段進行組織的,分隔符通常是制表符\t,如下所示:

seg_A	seg_B	seg_C
...
...
...

這種格式可以組織各種數據,比如日志文件,訓練/測試數據,用戶行為數據等,這些數據都是字符串的形式,并且按照每行一個樣本,每列一個字段的形式進行儲存。linux中有很多工具和命令處理此類數據非常方便,這里簡單筆記下。

打印某一列

采用awk可以做到。

cat your_file | awk -F "\t" '{print $1}' # 打印第一列
cat your_file | awk -F "\t" '{print $NF}' # 打印最后一列

查找字符串

采用sed, grep ,大殺器awk當然也可,不過沒必要。

cat your_file | sed -n '/string_pattern/p'
cat your_file | grep "your_string"
cat your_file | grep -E "string_pattern"

新增一列

采用awk, 假如原本的文件如:

# file: your_file
1	2	3
4	5	6
7	8	9

那么在最后一列添加上字符A,可以用以下腳本

cat your_file | awk -F "\t" '
BEGIN{string="A"}
{
	for(i = 0; i < NF; i++)
	{
		printf($i);
		printf("\t");
	}
	printf("%s\n", string);
}'

其輸出結果是:

1	2	3	A
4	5	6	A
7	8	9	A

我們發現awk的可執行代碼非常類似于C語言,并且awk是對每一行為單位進行處理的,這意味著以上的代碼會對文件中的每一行進行相同的操作。

替換字符串

替代字符串這個操作可以由非常多的工具進行,比如sed, tr, 萬能的awk等。個人喜歡用sed

cat your_file | sed -n 's/old_string/new_string/p'

大小寫字母轉換

tr命令適合用于字符串的轉換,壓縮和刪除。

echo "AbC" | tr -t [A-Z] [a-z]

輸出為abc

數據篩選

有時候需要對每一列的某些數值指標(離散的或者連續的)進行篩選,可以采用awk輕松搞定。原數據如:

# file: your_file
data_a	data_b	1.0
data_a	data_b	0.5
data_a	data_b	0.8
data_a	data_b	0.3
data_a	data_b	None

那么挑選所有最后一列大于0.5的行,可以

cat your_file | awk -F "\t" '$3>0.5'

輸出為:

data_a	data_b	1.0
data_a	data_b	0.8
data_a	data_b	None

為了篩出掉缺省值None,也可以選擇同時篩選多個條件,通過與(&&)或(||)非(?。┻B接起來,如下面的第一條

cat your_file | awk -F "\t" '$3>0.5 && $3!="None"'
cat your_file | awk -F "\t" '$3>0.5 && $3<0.8'
cat your_file | awk -F "\t" '$3<0.5 || $3>0.8'
cat your_file | awk -F "\t" '$3!=0'

求每一行數字的加和并且求平均值

cat your_file | awk -F "\t" '
BEGIN{sumv=0;line=0}
{
	sumv+=$2;
	line++;
}
END{print sumv/line}
'

awk引用shell環境變量

有時候需要awk訪問shell環境變量,此時不能簡單用${VAR}進行訪問,可以考慮以下兩種方式:

ENVVAR="..." 
cat file | awk -v var="${ENVVAR}" '{print var}' 

或者通過訪問內置的ENVIRON變量實現

export ENVVAR="..."
cat file | awk '{print ENVIRON["ENVVAR"]}'
unset ENVVAR # 為了后續的數據引用安全,unset掉

awk文件間查重

有時候需要對兩個文件之間某個字段的重復部分進行篩選,然后對提取出重復字段的整行部分。比如我們有以下數據:

file_1.data

http://haokan.baidu.com/v?pd=wisenatural&vid=7217158148519997092 A
https://zhidao.baidu.com/question/2054086297537323627/answer/3367935303.html B
http://m.bilibili.com/video/BV1Zw411d7m6 C
https://haokan.baidu.com/v?pd=wisenatural&vid=6619006578881460543 D
http://haokan.baidu.com/v?pd=wisenatural&vid=5651466905742673647 E

file_2.data

https://haokan.baidu.com/v?pd=wisenatural&vid=7217158148519997092 A
http://zhidao.baidu.com/question/2054086297537323627/answer/3367935303.html B
http://v.qq.com/boke/page/t/0/w/t01451r5euw.html C
http://3g.163.com/v/video/V5KLT7ESE.html D
http://haokan.baidu.com/v?pd=wisenatural&vid=5651466905742673647 E

那么可以通過以下awk腳本進行:

awk -F " " 'FNR==NR{a[$1];next} $1 in a {print $1}' file_1.data  file_2.data

那么會輸出:

http://haokan.baidu.com/v?pd=wisenatural&vid=5651466905742673647 E

其中的NR (Number of Records)表示程序開始累計讀取的記錄數,而FNR (File Number of Records)表示當前文件讀取的記錄數,當單文件執行時,兩者相同;當存在多文件時,FNR會在讀取新文件的時候重新置位為0,而NR會一直累計,因此可以用FNR==NR來判斷是否在讀取第一份文件。

我們會發現協議頭https://和http://即便不同,其url主體還是一致的,這種情況下需要進行split去除協議頭后進行對比,腳本如下:

awk -F " " -v seg="://" '
FNR==NR{split($1, b, seg);a[b[2]];next}  {
split($1, c, seg); if (c[2] in a) print $0
}' file_1.data  file_2.data

將會輸出:

https://haokan.baidu.com/v?pd=wisenatural&vid=7217158148519997092 A
http://zhidao.baidu.com/question/2054086297537323627/answer/3367935303.html B
http://haokan.baidu.com/v?pd=wisenatural&vid=5651466905742673647 E

awk文件去重

awk也可以用于當前文件中,對于某個字段進行去重處理,加入目前輸入文件如:

file.data

https://haokan.baidu.com/v?pd=wisenatural&vid=7217158148519997092 A
http://v.qq.com/boke/page/t/0/w/t01451r5euw.html C
http://zhidao.baidu.com/question/2054086297537323627/answer/3367935303.html B
http://v.qq.com/boke/page/t/0/w/t01451r5euw.html C
http://3g.163.com/v/video/V5KLT7ESE.html D
http://haokan.baidu.com/v?pd=wisenatural&vid=7217158148519997092 A
https://zhidao.baidu.com/question/2054086297537323627/answer/3367935303.html B
http://m.bilibili.com/video/BV1Zw411d7m6 C
http://haokan.baidu.com/v?pd=wisenatural&vid=7217158148519997092 A
https://haokan.baidu.com/v?pd=wisenatural&vid=6619006578881460543 D
http://haokan.baidu.com/v?pd=wisenatural&vid=5651466905742673647 E
http://haokan.baidu.com/v?pd=wisenatural&vid=7217158148519997092 A
http://haokan.baidu.com/v?pd=wisenatural&vid=5651466905742673647 E

那么在不考慮協議頭的差別的情況下(也就是只看url主體),去重腳本如下:

awk -F " " -v seg="://" '{
split($1,a,seg); if (a[2] in b) {next} else {b[a[2]]};print $0
}' file.data

輸出為:

https://haokan.baidu.com/v?pd=wisenatural&vid=7217158148519997092 A
http://v.qq.com/boke/page/t/0/w/t01451r5euw.html C
http://zhidao.baidu.com/question/2054086297537323627/answer/3367935303.html B
http://3g.163.com/v/video/V5KLT7ESE.html D
http://m.bilibili.com/video/BV1Zw411d7m6 C
https://haokan.baidu.com/v?pd=wisenatural&vid=6619006578881460543 D
http://haokan.baidu.com/v?pd=wisenatural&vid=5651466905742673647 E

單文件查重

有時候需要進行單文件查重,比如對某個字段進行查重,如下所示

file_1.data

part-00001.attempt_000.gz
part-00001.attempt_001.gz
part-00002.attempt_000.gz
part-00003.attempt_000.gz
part-00004.attempt_000.gz
part-00004.attempt_001.gz
part-00004.attempt_002.gz

其中的attempt_xxx是失敗重試的次數,那么對其進行查重可以用以下腳本:

cat file_1.data | awk '{
	split($0, tmp, ".");
	part_name = tmp[1];
	if (part_name in part_set) {
		print part_name, $0;
	} else {
		part_set[part_name];
	}
}'

由此可以將重復的part打印出來,當然由此也可以選擇未重復的part。

兩文件查重

有時候需要簡單統計兩個文件之間的某個字段重復程度,比如統計兩個文件重復的url數量,那么可以用grep實現,通過-x指定完全字符串匹配,-F將匹配模式指定為固定字符串的列表,用-f指定規則文件,其內容含有一個或多個規則樣式,讓grep查找符合規則條件的文件內容,格式為每行一個規則樣式。通過awk首先將字段進行轉儲,如:

cat url_1.data | awk -F "\t" '{print $1}' > tmp_url_1.data
cat url_2.data | awk -F "\t" '{print $1}' > tmp_url_2.data
grep -xFf tmp_url_1.data tmp_url_2.data

這樣可以統計tmp_url_2.data中的url有多少是在tmp_url_1.data出現過的。

更換分割字段的分隔符

有時候需要更改文件的分隔符,比如從"\t"轉成" ",那么可以用如下腳本:

# file.data: your_file
1	2	3
4	5	6
7	8	9
cat file.data | awk -F "\t" -v OFS=" " '{$1=$1; print $0}'

這里有個值得注意的就是: $0是awk中對于輸入record的記錄,不會由于設置了OFS輸出分隔符(Output Field Seperator )而變化,因此需要通過$1=$1進行$0值的重建。

提取括號內的值

有時候遇到的數據如下所示:

# file.data: your_file
date(20220114)time(0419pm)
date(20220114)time(0839pm)
...

需求是提取括號內的內容,那么可以用以下命令:

cat file.data | awk -F"[()]" '{print $2,$4}'

也還有很多命令可以實現這類型的需求,筆者以后繼續整理下

打印特定行的字符串

awk可以解決,但是最快的還是采用sed進行:

sed -n '2,$p' data.file  # 第二行到最后一行的所有數據
sed -n '100p' data.file # 第100行數據
sed -n '4,6p' data.file # 第4到第5行數據

字符串替換(正則模板)

通過正則表達式可以實現更為靈活的字符串查找和匹配,以sed為例子,假如當前文檔如:

# file.data
\mathcal{J} = \sum_{i=0]^{N-1} \mathcal{L}_i 
\tag{1-1}

有時候需要把所有\tag{}的字符串都去除,最好的方法就是采用正則表達式:

cat file.data | sed -e 's/\(.*\)\\tag{.*}\(.*\)/\1\2/p'

其中-e表示擴展正則表達式,s/reg_pattern/replace_str/p表示用replace_str去替換符合reg_pattern的字符串,其中\(\)是對括號的轉義,而()是表示一組字符串(在后續會用\1 \2進行指定),那么除去正則表達式,這個正則表達式的意思是(.*)\tag{.*}(.*) 也就是查找符合該模式的字符串。在replace_str域,\1 \2代表符合正則表達式的字符串組,那么其實\1 = "\mathcal{J} = \sum_{i=0]^{N-1} \mathcal{L}_i ", \2 = “”。[1]

字段挑選

如以下輸入,不同字段用空格隔開,但是由于某些原因,可能并不僅僅是一個空格,其中可能有若干個空格隔開了不同字段,可以考慮結合cut和tr進行字段挑選

NO Name SubjectID Mark 備注

1  longshuai 001  56 不及格
2  gaoxiaofang  001 60 及格
3  zhangsan 001 50 不及格
4  lisi    001   80 及格
5  wangwu   001   90 及格
cat abc.sh | tr -s " " | cut -d " " -f2,4

以上腳本對第2和4列字段進行打印,其中的tr -s將對重復的空格進行壓縮,輸出結果如:

Name Mark
longshuai 56
gaoxiaofang 60
zhangsan 50
lisi 80
wangwu 90

cut命令的參數有:

-b:按字節篩選;
-n:與"-b"選項連用,表示禁止將字節分割開來操作;
-c:按字符篩選;
-f:按字段篩選;
-d:指定字段分隔符,不寫-d時的默認字段分隔符為"TAB";因此只能和"-f"選項一起使用。
-s:避免打印不包含分隔符的行;
--complement:補足被選擇的字節、字符或字段(反向選擇的意思或者說是補集);
--output-delimiter:指定輸出分割符;默認為輸入分隔符。

當然,這個字段挑選的功能也可以由大殺器awk完成,但是有時候用cut會更精煉一些。

刪除重復字符有些場景中,可能會出現重復字符,這些字符可能是用戶的不規范輸入,或者其他各種原因產生的,比如最常見的是重復空格,或者重復的制表符等等,可以采用tr -s 命令進行重復字符的去除,如:

echo "sssssss" | tr -s "s" 
# 輸出為 s

查看grep結果的上下文

grep經常用于查看文本中出現的字符串內容,有時候需要查看其上下文,可以用以下參數:

grep -5 'parttern' inputfile //打印匹配行的前后5行
grep -C 10 'parttern' inputfile //打印匹配行的前后10行
grep -A 5 'parttern' inputfile //打印匹配行的后5行
grep -B 5 'parttern' inputfile //打印匹配行的前5行

Reference

[1]. https://unix.stackexchange.com/questions/78625/using-sed-to-find-and-replace-complex-string-preferrably-with-regex

[2]. https://article.itxueyuan.com/m9bPp

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 2
收藏 3
關注 52
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧
主站蜘蛛池模板: 国产精品爽爽久久久久久 | 刺激性视频黄页 | 国产精品人人爽人人做av片 | 冈江凛性色精品一区二区 | 国产激情视频网站 | 国产成人福利视频 | 精品日韩卡1二2卡3卡4卡乱码 | 欧美日韩免费一区二区 | 99在线99| 91肥熟 | www480jcom四虎 | 国产AV永久无码精品网站 | 丰满少妇被猛烈进出69影院 | 欧美兽交xxxx×视频 | 一区91| www.99日本精品片com | 亚洲ΑV无码一区二区三区四区 | 亚洲国产精品视频一区二区 | aaa一级毛片 | 日韩视频一区在线观看 | 免费91看片 | 三级毛片一 | 亚洲免费视频一区二区 | 亚洲欧美小说图片 | 北条麻妃国产九九九精品视频 | 日本视频黄 | 国产精品高清乱码在线观看 | 99久久综合狠狠综合 | 午夜1234 | 国产免费一区二区在线a片视频 | 国产成人午夜福利在线观看者 | 国产A级毛片色咪味 | 狂野欧美性猛交bbbb | 欧美激情一二三区 | 性做久久久久久免费观看软件 | 一性一交一伦一片A片庆乱码 | 亚洲高清无吗 | 国产免费麻豆 | 成人精品在线视频 | 国产在线精品无码不卡手机免费 | 精品国产第一福利网站 |