Bash script / awk เพื่อป้อนและส่งออกไฟล์ CSV

Sep 28 2020

ฉันมีปัญหาในการสร้างสคริปต์ bash / awk / sed ที่จะใช้ไฟล์ CSV ที่คั่นด้วยจุลภาคสามคอลัมน์ (ชื่อนามสกุลวันเดือนปีเกิด) และส่งออกไฟล์ CSV อื่นที่มีคอลัมน์เดียวกันจากอินพุตด้วย คอลัมน์เพิ่มเติมที่แสดงความแตกต่างระหว่างวันที่ปัจจุบันและวันเดือนปีเกิดในปี

$ yourscript <input CSV file> <output CSV file>

input.csv อาจมีลักษณะดังนี้:

bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972

output.csv ควรมีลักษณะดังนี้:

bob,wag,06/13/1958,62
ashley,hay,01/23/1983,37
evan,bert,09/11/1972,48

คำตอบ

3 Cbhihe Sep 28 2020 at 14:46
$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972

ในการส่งออกในไฟล์ที่ตั้งชื่อoutput-fileและแสดงเป็น STDOUT ในเวลาเดียวกัน:

$ 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

หรือเพียงแค่ส่งออกไปยังไฟล์เดียวกัน:

$ awk -v year=$(\date +%Y) 'BEGIN{FS="/"} {print $0 "," year-$3}' data > output-file
2 Cbhihe Sep 30 2020 at 18:04

เพื่อดำเนินการคำนวณเวลาที่ถูกต้องมากขึ้นคุณสามารถใช้gawk's เวลาและสตริงฟังก์ชั่น (ต่อ @ ข้อเสนอแนะของ AdminBee) ใช้ข้อมูลอินพุตเป็น:

$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972

คุณสามารถรับความแตกต่างของเวลาระหว่างวันนี้และวันที่ที่แสดงในแต่ละบรรทัดได้ด้วย:

$ 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

ตัวอย่างข้อมูล:

int((today-mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00))/(3600*24))

ทำสามสิ่งพื้นฐานสำหรับแต่ละบรรทัดของไฟล์อินพุต:

  • จะคำนวณเวลาที่ผ่านไป (เป็นวินาที) ตั้งแต่ 1970-01-01 00:00:00 UTC (บนระบบ POSIX) ไม่นับอธิกวินาทีด้วย mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00)
  • จะคำนวณความแตกต่างของเวลาระหว่างปริมาณข้างต้นและตัวแปรtodayซึ่งประกอบด้วยจำนวนวินาทีที่ผ่านไปในขณะดำเนินการตั้งแต่ 1970-01-01 00:00:00 UTC
  • มันแบ่งความแตกต่างในเวลาไม่กี่วินาทีโดย 3600 * 24 int()จะได้รับเดียวกันในวันและพิจารณาเฉพาะส่วนจำนวนเต็มของผลที่จะได้รับทั้งวันด้วย

คุณสามารถเล่นด้วยเพื่อให้เวลาของคุณแตกต่างกันเป็นวินาทีนาทีชั่วโมงตามความต้องการของคุณ HTH

MaheshK. Sep 28 2020 at 11:49

เพื่อให้ได้ความแตกต่างของวันที่คุณสามารถใช้ฟังก์ชันทุบตีขนาดเล็กนี้

ใช้หมายเลขต่อไปนี้สำหรับความต้องการของคุณ

  • # เพื่อรับความแตกต่างของวัน : 86400
  • # รับส่วนต่างปี : 31536000

ฟังก์ชันทุบตี

datediff() {
  current_date=$(date -d "$1" +%s)
  birth_date=$(date -d "$2" +%s)
  echo $(( (current_date - birth_date) / 31536000)) Years
}

การใช้งาน:

datediff '9/28/2020' '1/1/1999'

เอาท์พุต:

 21 years
MarcinŚlusarz Jan 09 2021 at 09:58

ขึ้นอยู่กับสิ่งที่คุณต้องการจริงๆ:

ความแตกต่างของปี:

(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

อายุ:

(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 และ csv-header มาจากcsv-nix-tools