[英]need to retain column spacing in awk script
看到了大量的例子,但我似乎無法從https://stackoverflow.com/a/72720612這個網站上的另一個用戶@Just Khaithang 在這個腳本中工作,它工作得很好,但我需要保留我的列間距為好吧,因為它很關鍵。 這是我在這里多次發布的 .txt 文件示例。 開頭有 1 個空格,從第 1 列的開頭到第 2 列的開頭有 20 個空格,在 2 和 3 之間有 4 個空格。腳本見下文。 結果改變了用戶輸入的日期,因此使用了變量$broken_date
。 使用awk -v
從另一個 shell 腳本調用此腳本。 工作之間的“”空格,但由於第 1 列不同,它沒有保持對齊。
146327A 0000000020220422 000002012633825-0003-1
137149D 0000000045220419 000004512632587-0003-0
137050C 0000000018220419 000001812632410-0003-0
137147A 0000000045220419 000004512632487-0003-0
137233B 0000000144220421 000014412630711-0003-1
137599B 0000000120220419 000012012632543-0003-0
137604D 0000000015220419 000001512632588-0003-0
151031-001E 0000000041220517 000004112575320-0003-1
151248-001A 0000000021220421 000002112629944-0003-1
151249-001A 0000000005220422 000000512634524-0003-1
151827-002B 0000000040220421 000004012629223-0003-1
127941B 0000000045220422 000004512634676-0003-1
137105A 0000000020220421 000002012630791-0003-1
132136A 0000000005220419 000000512632590-0003-0
132137A 0000000005220419 000000512632591-0003-0
134180D 0000000052220419 000006012622399-0003-1
134307-004K 0000000016220420 000001612635621-0003-0
141014-001B 0000000040220419 000004012632585-0003-0
{
c2=$2
c3=$3
sub("0+","",c2)
sub("0+","",c3)
sub("-.*","",c3)
if (length(c2) == 8) {
c2_value=substr(c2,1,2)
} else if (length(c2) == 9) {
c2_value=substr(c2,1,3)
}
if (length(c3) == 10) {
c3_value=substr(c3,1,2)
} else if (length(c3) == 11) {
c3_value=substr(c3,1,3)
}
if(c2_value != c3_value) {
sub("[1-9].*$","",$2)
date="$broken_date" # this value taken from user input
print $1" "$2 c2_value broken_date" "$3
} else {
print $0
}
}
輸出應該是
146327A 0000000020220422 000002012633825-0003-1
137149D 0000000045220419 000004512632587-0003-0
137050C 0000000018220419 000001812632410-0003-0
137147A 0000000045220419 000004512632487-0003-0
137233B 0000000144220421 000014412630711-0003-1
137599B 0000000120220419 000012012632543-0003-0
137604D 0000000015220419 000001512632588-0003-0
151031-001E 0000000041220517 000004112575320-0003-1
151248-001A 0000000021220421 000002112629944-0003-1
151249-001A 0000000005220422 000000512634524-0003-1
151827-002B 0000000040220421 000004012629223-0003-1
127941B 0000000045220422 000004512634676-0003-1
137105A 0000000020220421 000002012630791-0003-1
132136A 0000000005220419 000000512632590-0003-0
132137A 0000000005220419 000000512632591-0003-0
134180D 0000000052220909 000006012622399-0003-1
134307-004K 0000000016220420 000001612635621-0003-0
141014-001B 0000000040220419 000004012632585-0003-0
唯一的區別在於日期,但這就是我在輸入 220909 的底部第二列的第三行需要做的事情。
我通過 MKS Toolkit 在 Korn shell 中執行此操作; awk 說文件版本為 9.2.3.2096。 這是在舊的 Windows XP 機器上。
這將與使用任何 awk 的行為相同:
$ cat tst.sh
#!/usr/bin/env bash
broken_date='220909'
awk -v broken_date="$broken_date" '
substr($2,4,7) != substr($3,1,7) {
tail = $0
nf = 0
while ( tail != "" ) {
match(tail,/^[ \t]*/)
sep[++nf] = substr(tail,RSTART,RLENGTH)
tail = substr(tail,RSTART+RLENGTH)
match(tail,/^[^ \t]*/)
fld[nf] = substr(tail,RSTART,RLENGTH)
tail = substr(tail,RSTART+RLENGTH)
}
fld[2] = substr(fld[2],1,10) broken_date
$0 = ""
for ( i=1; i<=nf; i++ ) {
$0 = $0 sep[i] fld[i]
}
}
{ print }
' "${@:--}"
$ ./tst.sh file
146327A 0000000020220422 000002012633825-0003-1
137149D 0000000045220419 000004512632587-0003-0
137050C 0000000018220419 000001812632410-0003-0
137147A 0000000045220419 000004512632487-0003-0
137233B 0000000144220421 000014412630711-0003-1
137599B 0000000120220419 000012012632543-0003-0
137604D 0000000015220419 000001512632588-0003-0
151031-001E 0000000041220517 000004112575320-0003-1
151248-001A 0000000021220421 000002112629944-0003-1
151249-001A 0000000005220422 000000512634524-0003-1
151827-002B 0000000040220421 000004012629223-0003-1
127941B 0000000045220422 000004512634676-0003-1
137105A 0000000020220421 000002012630791-0003-1
132136A 0000000005220419 000000512632590-0003-0
132137A 0000000005220419 000000512632591-0003-0
134180D 0000000052220909 000006012622399-0003-1
134307-004K 0000000016220420 000001612635621-0003-0
141014-001B 0000000040220419 000004012632585-0003-0
它只是保留您已有的任何間距。 我使腳本比必要的更通用,因此您可以了解如何將輸入記錄分解為分隔符數組 ( sep[]
) 和字段 ( fld[]
),這樣您以后就可以對類似問題做任何您想做的事情。
假設:
GNU awk/FIELDWIDTHS
可供 OP 使用(在評論中 OP 提到無法讓FIELDWIDTHS
工作,我認為這意味着 OP 正在運行GNU awk
否則我希望 OP 說明錯誤或FIELDWIDTHS
不可用) 修改 OP 當前代碼以使用GNU awk/FIELDWIDTHS
的一種想法:
broken_date='220909'
awk -v bdate="${broken_date}" '
BEGIN { FIELDWIDTHS="21 20 100"
fmt="%-21s%-20s%s\n" # define our printf format to match FIELDSWIDTHS
}
{ c2=$2; gsub(/ /,"",c2); sub("0+","",c2)
c3=$3; gsub(/ /,"",c3); sub("0+","",c3); sub("-.*","",c3)
if (length(c2) == 8) { c2_value=substr(c2,1,2) }
else if (length(c2) == 9) { c2_value=substr(c2,1,3) }
if (length(c3) == 10) { c3_value=substr(c3,1,2) }
else if (length(c3) == 11) { c3_value=substr(c3,1,3) }
if (c2_value != c3_value) { printf fmt,$1,substr($2,1,length(gensub(/ /,"","g",$2))-6) bdate,$3 }
else { print $0 }
}
' x > y
在保持FIELDWIDTHS
方法的同時,重新設計 OP 邏輯(也解決length(c3) == 9
問題):
broken_date='220909'
awk -v bdate="${broken_date}" '
BEGIN { FIELDWIDTHS="21 20 100"
fmt="%-21s%-20s%s\n"
}
{ c2=$2;
gsub(/^[0]+| /,"",c2 ) # strip leading zeroes and all spaces
c2=substr(c2,1,length(c2)-6) # strip off last 6 characters
pfx=$2 # find the prefix of $2
gsub(/ /,"",pfx) # strip all spaces
pfx=substr(pfx,1,length(pfx)-6) # strip off last 6 characters
split($3,a,"-") # split $3 on hyphens
c3=a[1] # grab 1st hyphen delimited field
gsub(/^[0]+| /,"",c3) # strip leading zeroes and all spaces
c3=substr(c3,1,length(c3)-8) # strip off last 8 characters
if (c2 != c3) $2=pfx bdate # replace $2 with its prefix + bdate (aka broken_date)
printf fmt,$1,$2,$3
}
' x > y
這兩個生成:
$ diff x y
16c16
< 134180D 0000000052220419 000006012622399-0003-1
---
> 134180D 0000000052220909 000006012622399-0003-1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.