基於 ‘_’ 在 Bash 中拆分列
您好,我遇到了與這篇文章中的問題類似的問題
但由於我是 Bash 新手,而且我的文件有點不同,我無法修改並將答案應用於我的程式碼。
我有一個包含多列的 csv 文件(所有列都以逗號分隔),我要拆分的列如下所示:(輸入文件)
post_id 86680728811_272953252761568 86680728811_273859942672742 86680728811_281125741936891 86680728811_10150500662053812 _86680728811_10150500969563812 86680728811_10150501303143812 86680728811_305275689511038 _86680728811_10150501624593812 86680728811_10150501873973812 86680728811_145945585518261
我想提取第二個 ID 號(下劃線後面的那個)。請記住,有些列以數字開頭,有些以空格開頭,有些以“_”開頭。
我想要的輸出是添加兩個新列,每個列都包含由“_”分隔的 ID。第一行範例:
page ID post ID 86680728811 272953252761568
我嘗試使用正則表達式來讀取數字:
awk -F',' '{print $2} /(?<=_)[0-9]+/' FB_Dataset.csv
但到目前為止,我所嘗試的一切都沒有奏效。任何建議都會有所幫助。謝謝
這對你有用嗎?我將採用這種格式:
A B C post_id a,b,c,86680728811_272953252761568 a,b,c, 86680728811_273859942672742 a,b,c,86680728811_281125741936891 a,b,c,86680728811_10150500662053812 a,b,c,_86680728811_10150500969563812 a,b,c,86680728811_10150501303143812 a,b,c,86680728811_305275689511038 a,b,c,_86680728811_10150501624593812 a,b,c, 86680728811_10150501873973812 a,b,c,86680728811_145945585518261
然後是命令
cat file | sed -Ee 's/(.*)post_id/\1page ID post I/' -e 's/,[_ ]/,/' -e 's/_/,/'
輸出:
A B C page ID post ID a,b,c,86680728811,272953252761568 a,b,c,86680728811,273859942672742 a,b,c,86680728811,281125741936891 a,b,c,86680728811,10150500662053812 a,b,c,86680728811,10150500969563812 a,b,c,86680728811,10150501303143812 a,b,c,86680728811,305275689511038 a,b,c,86680728811,10150501624593812 a,b,c,86680728811,10150501873973812 a,b,c,86680728811,145945585518261
-E
使用擴展正則表達式 (GNU),以便可以擷取組。更改標題以添加
page ID post ID
擷取第一個組(.*)
直到post_id
,並將其替換為擷取的組\1
和page ID post ID
's/(.*)post_id/\1page ID post ID/'
從逗號後面的行中刪除前導空格和下劃線
_
,並將其替換為單個逗號。sed 's/,[_ ]/,/'
_
最後,用逗號替換下劃線。sed 's/_/,/'
請注意,我刪除了
cut
不必存在的命令(這是我嘗試過的其他命令的提醒)
awk -F', *_?' -v OFS=, ' NR==1 { for (i=1;i<=NF;i++) { if ($i == "post_id") { $i = "page ID" OFS "post ID"; col=$1; }; }; print; next }; { split($col,a,/_/); $col=a[1] OFS a[2]; print; }; ' FB_Dataset.csv
因為您顯示的欄位數據的格式不一致(有些以空格開頭,有些以下劃線開頭,也許有些兩者兼有),所以此
awk
腳本使用正則表達式, *_?
(“逗號後跟零個或多個空格,並且可選後跟一個下劃線") 作為欄位分隔符 (FS
)。它還將輸出欄位分隔符 (
OFS
) 設置為逗號。在讀取輸入時,它會以不同方式處理第一行(CSV 標題)和所有剩餘的行:
對於第一行 (
NR==1
),它檢查每個欄位的值,查找字元串"post_id"
。如果找到該字元串,它會更改該欄位的值,使其具有兩個新欄位名稱 (page ID
和post ID
),由OFS
. 它還將該欄位的索引號儲存在變數col
中以供以後使用。最後,它列印修改後的行。這假定欄位名稱是唯一的,因為它們應該是有效的 CSV 文件。如果多個欄位具有 name ,它將無法正常工作
post_id
。對於剩餘的行,它使用下劃線 ( ) 字元作為分隔符將欄位拆分
$col
為數組。然後它將 $col 替換為該數組的前兩個元素,由. 然後它列印修改後的行。a``_``OFS
樣本輸入:
A,B,C,post_id,D,E,F a,b,c,86680728811_272953252761568,d,e,f a,b,c, 86680728811_273859942672742,d,e,f a,b,c,86680728811_281125741936891,d,e,f
樣本輸出:
A,B,C,page ID,post ID,D,E,F a,b,c,86680728811,272953252761568,d,e,f a,b,c,86680728811,273859942672742,d,e,f a,b,c,86680728811,281125741936891,d,e,f
在標題行中,該
post_id
欄位已被轉換為兩個欄位(page ID
和post ID
),而在 CSV 數據中,相應的欄位已被拆分為兩個欄位。順便說一句,因為腳本在標題行中搜尋匹配的欄位名稱 (
post_id
),所以它可以處理我們要拆分的欄位之前和/或之後的任意數量的欄位。有了這個樣本數據,發現第四個欄位包含了我們想要的名字,所以col=4
請注意,
$i
並且$col
在 awk 中的含義與在 shell 中的含義不同。
- 在 shell 中,它們表示名稱為
i
和的變數col
。- 在
awk
中,它們的意思是“索引號等於變數i
(或變數col
)的值的欄位的值”。即它通過間接訪問欄位。例如,如果
i=1
then$i
表示“欄位 1 中的值”,則與$1
.例如,如果您需要對欄位編號執行算術運算,這很有用。在 awk 中,
NF
是一個自動創建的變數,包含目前輸入行的最後一個欄位的索引號。so$NF
表示“最後一個欄位中的值”,$(NF-1)
表示“倒數第二個欄位中的值”,依此類推。