我有一個檔案有這個:
cat textfile.csv
Name,Age,City
Jen,40,San Diego
Jen,,NYC
Bob,29,Miami,
,30,Boston
Jen,,NYC
Bob,21,Seattle
而不是使用 vim 手動執行此操作.. 有沒有辦法可以使用 awk/sed 將 2nd Jen 的年齡從 , 編輯到我想要的任何值?
另請注意如何有 2 Jen,,NYC ...我希望能夠選擇 2nd Jen,,NYC (在西雅圖之上)并編輯那個
最終這個檔案會增長,并且可能有超過 1 個 Bob/Jen,所以我希望能夠定位我想要的特定 Jen,并在需要時編輯欄位(無論是姓名、年齡、城市)。
uj5u.com熱心網友回復:
這里嘗試解決方案:
修改.bash
#!/bin/bash
# Arguments
# $1: name to find
# $2: previous line
# $3: new age
if [[ $# -eq 3 ]]
then
name="$1"
previous="$2"
newage="$3"
else
echo "Usage: $0 <name> <previous> <newage>"
exit 1
fi
# CSV input file
csvfile="textfile.csv"
if [[ ! -f "$csvfile" ]]
then
echo "ERROR: cannot find file $csvfile"
exit 1
fi
# awk script
if [[ ! -f modify.awk ]]
then
echo "ERROR: missing awk script modify.awk"
exit 1
fi
awk -f modify.awk -v previous="$previous" name="$name" newage="$newage" textfile.csv
- 這個 bash 腳本只是 awk 腳本的包裝器,用于處理引數并進行一些驗證。
-vofawk允許您創建awk可以在其代碼中使用的變數。- 變數值必須雙引號才能正確處理空格。
- 該腳本在不修改原始檔案的情況下將結果列印到螢屏上。該輸出可以使用
>newfile.
修改.awk
BEGIN { FS="," }
$0~previous {
f = 1
print
next
}
f && $0~name {
f = 0
print $1 "," newage "," $3
next
}
{ f = 0; print }
- 由于 awk 需要匹配存盤在變數中的模式,因此請使用語法
$0~VARIABLE而不是/pattern/. - 如果
previous找到模式,設定f = 1. - 當
f == 1AND(此處為 &&)找到名稱時,列印名稱(第一個欄位)、新年齡(存盤在變數中)和城市。并且不要忘記將 f 設定回 0。 - 最后重置 f,列印該行并繼續。
使用這些腳本
修改跟隨波士頓市的線路中 Jen 的年齡。
$ modify.bash Jen Boston 99與以前相同,但在“圣地亞哥”行之后修改了 Jen。
$previous這說明了在涉及空間時如何設定。$ modify.bash Jen "San Diego" 99再次相同,但這次指定整個前一行。由于模式可以是任何東西,只要匹配,就可以了。
$ modify.bash Jen ",30,Boston" 99
uj5u.com熱心網友回復:
我會AWK按照以下方式使用 GNU 來完成這項任務,假設你想將年齡設定為 2ndJen,,NYC并35讓textfile.csv內容成為
Name,Age,City
Jen,40,San Diego
Jen,,NYC
Bob,29,Miami,
,30,Boston
Jen,,NYC
Bob,21,Seattle
然后
awk -i inplace 'BEGIN{FS=OFS=","}$0=="Jen,,NYC"{cnt =1;if(cnt==2){$2=35}}{print}' textfile.csv
將textfile.csv內容更改為
Name,Age,City
Jen,40,San Diego
Jen,,NYC
Bob,29,Miami,
,30,Boston
Jen,35,NYC
Bob,21,Seattle
說明:我通知 GNUAWK欄位分隔符 ( FS) 和輸出欄位分隔符 ( OFS) 都是,. 然后,如果當前處理的行 ( $0) 是Jen,,NYC我將cnt值增加1. if的值cnt等于2我將第二個欄位值設定為35。對于每一行,改變與否,我print都知道。您可能會選擇不先運行,-i inplace因此 GNUAWK將輸出到標準輸出,檢查它是否確實提供了您想要的,然后應用-i inplace.
(在 gawk 4.2.1 中測驗)
uj5u.com熱心網友回復:
將 GNU awk 用于-i inplace:
$ awk -i inplace '($0=="Jen,,NYC") && ( cnt==2){$0="Jen,27,NYC"} 1' testfile.csv
$ cat testfile.csv
Name,Age,City
Jen,40,San Diego
Jen,,NYC
Bob,29,Miami,
,30,Boston
Jen,27,NYC
Bob,21,Seattle
uj5u.com熱心網友回復:
使用嵌套sed運算式,可以定位匹配的確切行。要定位以 開頭的第二行Jen,必須排除第一行,0,/^Jen/!后跟一個嵌套運算式,以防止該命令影響進一步的匹配。
$ sed '0,/^Jen\>/!{0,/^Jen\>/s/^Jen,/&31/}' input_file
Name,Age,City
Jen,40,San Diego
Jen,31,NYC
Bob,29,Miami,
,30,Boston
Jen,,NYC
Bob,21,Seattle
$ sed '0,/^Jen\>/!{0,/^Jen\>/!{0,/^Jen\>/s/^Jen,/&31/}}' input_file
Name,Age,City
Jen,40,San Diego
Jen,,NYC
Bob,3129,Miami,
,3130,Boston
Jen,31,NYC
Bob,21,Seattle
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/471552.html
