Thay đổi mục cuối cùng trong danh sách được phân cách bằng dấu phẩy


8

Tôi có một tệp văn bản lớn trông như thế này:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,3
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,8
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,12

Đầu ra mong muốn là đây:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

Tôi đã thử các bài đăng có liên quan khác ở đây và trên các cộng đồng khác nhưng không thể có được chính xác những gì tôi muốn.

CẬP NHẬT

Đây là câu hỏi chéo (tôi muốn cả câu trả lời Unix / perl và giải pháp batch / powershell cho việc này.) Có câu trả lời thú vị.

Câu trả lời:


14

Cách tiếp cận awk vớichức năng sprintf (để thêm các số 0 đứng đầu):

awk -F, -v OFS=',' '$8=sprintf("MI-%02d",$8);' file

Đầu ra:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

-F,- đặt dấu phẩy ,làm dấu tách trường

$8 - chỉ vào trường thứ tám

%02d- định dạng coi đối số hàm là số có 2 chữ số


Lưu ý , trường cuối cùng trong một bản ghi có thể được trình bày bởi$NF.

NF là biến được xác định trước có giá trị là số trường trong bản ghi hiện tại

Vì vậy, $NFgiống như $8(cho đầu vào của bạn)

awk -F, -v OFS=',' '$(NF)=sprintf("MI-%02d", $(NF))' file

1
Một từ cảnh báo (không liên quan trong ví dụ này, nhưng có thể áp dụng trong các trường hợp khác): thay đổi giá trị của một trong các trường (ở đây: $ 8) "tính toán lại" toàn bộ các trường và có hiệu ứng phụ: ex1: mất 'nhiều dấu tách ': echo "1   2 3    4" | awk '{$2=$2;print $0}'cho: 1 2 3 4(chỉ còn 1 khoảng trắng (hoặc OFS) giữa các trường). ex2) echo "1,,,2,3,,,,4" | awk -F',' '{$2=$2;print $0}'cho: 1   2 3    4(dấu phẩy trở thành khoảng trắng). Có thể có tác dụng phụ khác. Kiểm tra và thực hiện một cách tiếp cận khác (gsub trên một biến sao chép là $ 0, ví dụ) nếu việc đánh cắp một trường có tác dụng phụ bất lợi.
Olivier Dulac

3

Bạn có thể thử sử dụng awk:

awk 'BEGIN { FS = OFS = "," } { $NF = sprintf("MI-%02d", $NF); } 1' file

2

Đây là giải pháp perl:

$ perl -F',' -lane '$last=$#F;$F[$last]=sprintf("MI-%02d",$F[$last]);print join ",", @F' input.txt                                       
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

Các -alá cờ cho phép chúng ta đầu vào điều trị như mảng, dựa trên phân định với -F. Về cơ bản chúng ta thay đổi mục cuối cùng trong mảng đó và xây dựng lại nó thông qua joinlệnh.


Cảm ơn bạn vì câu trả lời. Nó có ích nếu ai đó cần perl nhưng vẫn sprintflà ý tưởng cốt lõi cho câu trả lời của bạn. Không giống như nếu nó không đúng, chỉ là không cung cấp một cái gì đó khác với câu trả lời được chấp nhận. Dù sao +1.
M--

1
@Masoud tốt, lý do chính ở đây là vì sprintf()thường được sử dụng khi viết một chuỗi định dạng cụ thể vào một biến, đó là lý do tại sao nó được sử dụng trong nhiều ngôn ngữ khác. Tôi cũng có thể viết nó bằng Python - Python không có sprintf()nhưng ý tưởng cốt lõi sẽ giống nhau bất kể - viết chuỗi được định dạng vào một biến. Ngoài ra, chúng ta có thể thao tác trên các mục mảng trực tiếp và chỉ cần in chúng. Với loại câu hỏi này có số lượng giải pháp hữu hạn, về cơ bản là những gì tôi đang cố gắng nói
Sergiy Kolodyazhnyy

1

Với dữ liệu đầu vào như:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,3  
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,8  
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,14  
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,12  

trong text.csv

mã dưới đây

awk -F"," '{ i = 0;
  MyOutLine = "";
  j = NF - 1;
  while ( i < j ) {
    i++;
    MyOutLine = MyOutLine""$i",";
  }
  i++;
  x = sprintf( "%.2i", $i );
  y = "MI-"x;
  MyOutLine = MyOutLine""y;
  print MyOutLine; }' ./text.csv  

tạo ra sản lượng như:

36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-03
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-08
36,53,90478,0.58699759849,0.33616,4.83449759849,0.0695335954050315,MI-14
36,53,15596,0.58454577855,0.26119,2.24878677855,0.116147072052964,MI-12

1

Tcl

Đây là giải pháp của tôi, được thực hiện bằng cách sử dụng Tcl đọc từ tệp input.csv và đặt kết quả vào tệp output.csv

set in [open input.csv]
set out [open output.csv w]

while {![eof $in]} {
   set line [gets $in]
   set last_comma_pos [string last , $line]
   puts $out [string range $line 0 $last_comma_pos][format MI-%02d [string range $line $last_comma_pos+1 end]]
}

close $in
close $out

trình diễn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.