Câu trả lời:
Các -F
tùy chọn cần một cuộc tranh cãi: -F,
ví dụ.
Phần cuối của awk
tập lệnh phải được phân tách bằng dấu cách (dấu cách) với phần còn lại của các tham số.
Nếu dấu tách trường là ,
và bạn muốn giữ nó, và nếu số cột không đổi và thấp hơn hoặc bằng 11, hãy thử điều này:
awk -F, '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' OFS=, "$file"
command file > newfile && mv newfile file
. Điều đó nói rằng, phiên bản mới hơn của GNU awk
để hỗ trợ này : gawk -i inplace '{blah blah}' file
.
mv newfile file
bạn có thể sử dụng cat newfile > file ; rm -f newfile
- điều này bảo tồn inode và quyền của file
.
mktemp
thay vì tên tệp tạm thời được mã hóa cứng thành tập lệnh. ví dụtf=$(mktemp) ; command file > "$tf" ; cat "$tf" > file ; rm -f "$tf"
Giải pháp ngắn hơn sẽ là
awk -F',+' -v OFS=, '{$(NF+1)=$7; $7=""; $0=$0; $1=$1}1' file
Tôi không chắc liệu ,+
sẽ hoạt động trong tất cả các awk
phiên bản hay không, nhưng hoạt động ít nhất là trong GNU awk, cũng với -c
chế độ tương thích.
Giải trình:
$(NF+1)=$7
: đầu tiên chúng ta thêm trường thứ 7 vào cuối dòng (có thể $12=$7
trong trường hợp này)$7=""
: trong bước tiếp theo, trường thứ 7 bị xóa (nhưng các dấu phân cách xung quanh vẫn ở lại)$0=$0
) coi nhiều dấu phẩy là dấu tách trường (điều này được thực hiện thông qua -F',+'
, ở đây +
có nghĩa là một hoặc nhiều lần) và cũng sắp xếp lại bản ghi hiện tại thông qua $1=$1
để buộc xây dựng lại dòng bằng cách sử dụng trường đầu ra được thiết lập trước đó dấu phân cách (được đặt bởi một tùy chọn -v OFS=,
)1
Ví dụ đầu vào:
1,2,3,4,5,6,7,8,9,10,11
đầu ra
1,2,3,4,5,6,8,9,10,11,7
,+
sẽ hoạt động.
all,ball,call,,,fall
→ all,ball,call,fall
). (2) $(NF+1)=$7
là một cách tiếp cận thông minh. IMHO, $0 = $0 OFS $7
rõ ràng hơn một chút, chỉ có một vài nhân vật dài hơn và dường như nó cũng làm điều tương tự. Bạn có thể nghĩ về một tình huống trong đó $0 = $0 OFS $7
không làm giống như mã của bạn không?
$0=$0 OFS $7
có lẽ giống hệt $(NF+1)=$7
, nhưng chỉ với phần còn lại của mã không thay đổi, không nói chung.
Bạn có thể có nghĩa là:
awk -F, -v OFS='' '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' "$file"
awk
không bao giờ nhìn thấy các trích dẫn duy nhất OFS=''
, phải không? Bạn cũng có thể chỉ cần gõ OFS=
; nó giống hệt nhau
Bạn không nói cụ thể là bạn muốn sử dụng awk và bạn đã nói rằng bạn muốn sử dụng chỉnh sửa tại chỗ như được cung cấp bởi sed -i
, vì vậy đây là một sed -i
biến thể. Thường awk
là tốt hơn để làm việc với các cột, nhưng đây là một trường hợp mà tôi thích sed
, bởi vì nó tự nhiên xử lý số lượng cột tùy ý.
MOVECOL=7
N=$((MOVECOL-1))
sed -r -e "s/^(([^,]*,){$N})([^,]*),(.*)/\1\4,\3/" -i test.csv
Giải trình:
-r
chọn regexps mở rộng để chúng tôi tránh nhiều dấu gạch chéo ngượcTất nhiên điều này sẽ không hoạt động với các tệp ẩn dấu phẩy trong dấu ngoặc kép (hoặc tệ hơn là thoát chúng), nhưng awk sẽ không xử lý việc đó nếu không có một số màn nhào lộn nghiêm trọng. Nếu bạn gặp vấn đề đó, bạn nên sử dụng perl
mô-đun Text:CSV
hoặc python
mô-đun csv
.
Một vài awk
biến thể (giả sử tệp của bạn nằm trong biến $file
)
Tại đây, bạn có thể quay vòng cho tất cả các cột màu, in bằng dấu tách trường (OFS) và in dấu kết thúc bản ghi (ORS) ở cuối dòng.
awk -F',' -v OFS=, \
'{for(i=1;i<=NF;i++) if (i!=7) printf "%s",$i OFS; \
printf "%s",$7;printf ORS}' "$file"
Ở đây với việc sử dụng regex và gensub()
hàm
gawk -F',+' -v OFS=, '{$0=gensub(/\s*\S+/,"",7) OFS $7}1' "$file"
giết trường thứ 7 và in nó ở cuối dòng.
$0
là toàn bộ hồ sơ $n
là kỷ lục thứ nNF
là số lượng các lĩnh vực của dòng hiện tại OFS
đầu ra nộp dấu phân cáchORS
bộ kết thúc bản ghi đầu ra1
là mẹo để nói với awk true
và in mặc định ( $0
).Cập nhật ...
Tôi gần như quên mất, có thể thay đổi tất cả các cột theo sau cột thứ 7 .
awk -F',' -v OFS=, '{tmp=$7; for(i=7;i<=NF;i++) $i=$(i+1); $NF=tmp}1 ' "$file"
OFS $7
sẽ mạnh mẽ hơn "," $7
. (2) Tôi tin rằng điều đó ", " $7
là sai, trong chừng mực vì câu hỏi chỉ ra rằng OP không muốn có khoảng trắng sau dấu phẩy. (Và, nếu dữ liệu đầu vào có khoảng trắng sau dấu phẩy, thì $7
nó sẽ bắt đầu bằng một khoảng trắng và bạn sẽ thêm một khoảng trống.)
OFS $7
không chỉ mạnh mẽ hơn, mà thậm chí còn chung chung hơn ( "sự vội vàng làm lãng phí" )
^
hiệu cho biết phần cụ thể của lệnh gặp lỗi.