Bash script / awk để nhập và xuất tệp CSV
Tôi đang gặp sự cố khi tạo tập lệnh bash / awk / sed sẽ lấy tệp CSV được phân tách bằng dấu phẩy gồm ba cột (tên, họ, ngày sinh) và xuất ra một tệp CSV khác có cùng các cột từ đầu vào bằng một cột bổ sung hiển thị sự khác biệt giữa ngày hiện tại và ngày sinh trong năm.
$ yourscript <input CSV file> <output CSV file>
input.csv có thể trông giống như sau:
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
output.csv sẽ giống như sau:
bob,wag,06/13/1958,62
ashley,hay,01/23/1983,37
evan,bert,09/11/1972,48
Trả lời
$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
Để xuất ra một tệp có tên output-filevà hiển thị thành STDOUT cùng lúc:
$ awk -v year=$(\date +%Y) 'BEGIN{FS="/"} {print $0 "," year-$3}' data | tee output-file
bob,wag,06/13/1958,62
ashley,hay,01/23/1983,37
evan,bert,09/11/1972,48
Hoặc chỉ xuất ra cùng một tệp:
$ awk -v year=$(\date +%Y) 'BEGIN{FS="/"} {print $0 "," year-$3}' data > output-file
Để thực hiện các phép tính thời gian chính xác hơn, bạn có thể sử dụng gawkcác hàm thời gian và chuỗi (theo gợi ý của @ AdminBee). Sử dụng dữ liệu đầu vào như:
$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
Bạn có thể nhận được chênh lệch thời gian tính theo ngày từ bây giờ đến ngày được hiển thị trên mỗi dòng, với:
$ awk -F, 'BEGIN{today=systime()}
{print $0 "," int((today-mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00))/(3600*24))}' \
data | tee output-file
bob,wag,06/13/1958,22755
ashley,hay,01/23/1983,13765
evan,bert,09/11/1972,17551
Đoạn mã:
int((today-mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00))/(3600*24))
thực hiện ba điều cơ bản cho mỗi dòng của tệp đầu vào:
- nó tính toán thời gian đã trôi qua (tính bằng giây) kể từ 1970-01-01 00:00:00 UTC (trên hệ thống POSIX), không tính giây nhuận, với
mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00) - nó tính toán chênh lệch thời gian giữa đại lượng trên và biến
today, chứa số giây đã trôi qua tại thời điểm thực hiện kể từ 1970-01-01 00:00:00 UTC. - nó chia chênh lệch thời gian theo giây cho 3600 * 24 để lấy số ngày bằng nhau và chỉ xem xét phần nguyên của kết quả, để lấy nguyên ngày
int().
Bạn có thể chơi với nó để nhận chênh lệch thời gian tính theo giây, phút, giờ theo nhu cầu của bạn. HTH
Để có được sự khác biệt về ngày tháng, bạn có thể sử dụng hàm bash nhỏ này
Sử dụng các số sau cho nhu cầu của bạn
- # Để nhận chênh lệch ngày : 86400
- # Để nhận Chênh lệch theo năm : 31536000
Hàm Bash
datediff() {
current_date=$(date -d "$1" +%s)
birth_date=$(date -d "$2" +%s)
echo $(( (current_date - birth_date) / 31536000)) Years
}
Sử dụng:
datediff '9/28/2020' '1/1/1999'
Đầu ra:
21 years
Tùy thuộc vào những gì bạn thực sự muốn:
chênh lệch năm:
(echo "firstname,lastname,d"; cat input.csv) | csv-sqlite \
"select *, strftime('%Y', 'now') - substr(d, 7, 4) as year_diff
from input" | csv-header --remove
tuổi tác:
(echo "firstname,lastname,d"; cat input.csv) | csv-sqlite
"select *, strftime('%Y', 'now') - substr(d, 7, 4) -
case when strftime('%m%d', 'now') >= (substr(d, 1, 2) || substr(d, 4, 2))
then 0 else 1 end as age
from input" | csv-header --remove
csv-sqlite và csv-header là từ csv-nix-tools