BASH重新排列文件

时间:2017-08-04 23:52:24

标签: bash awk

我有一个这样的文件:

A345435;3/12/2016
D564565;12/29/2017
...

我试图把文件拿到这个:

A345435;20160312
D564565;20171229
...

我试过AWK,但我得到第一部分确定,日期总是一样。

awk 'BEGIN {FS=OFS=";"} {"date -d"$2" +%Y%m%d" | getline newDate; close(newDate); print $1,newDate}'

A345435;20160312
D564565;20160312
...

是不是真的有必要使用AWK,但我想避免的是循环文件,因为它有~20k行。

5 个答案:

答案 0 :(得分:3)

您只需要:

$ awk -F'[;/]' '{printf "%s;%s%02d%02d\n",$1,$4,$2,$3}' file
A345435;20160312
D564565;20171229

答案 1 :(得分:2)

你只是重新排列现有的字符串;你不必通过日期功能或外部程序进行转换

awk 'BEGIN {FS=OFS=";"}
  {split($2, mdy, "/");
   print $1, sprintf("%4d%02d%02d", mdy[3], mdy[1], mdy[2]);
  }' datafile

分成几行以便于阅读 - 如果你愿意,你可以放一行

答案 2 :(得分:0)

我不知道awk,但可以sed

完成(杂乱无章)
sed -e 's@;\([[:digit:]]\)/@;0\1/@' -e 's@/\([[:digit:]]\)/@/0\1/@' \
-e 's@;\([[:digit:]]\+\)/\([[:digit:]]\+\)/\([[:digit:]]\+\)@;\3\1\2@' yourfile

第一个表达式需要任意一天,并在它们前面加上0,第二个表达式在几个月内表示相同,第三个表达式在日,月和年中取三个数字,并根据需要对它们进行格式化。我使用了' @'标志而不是正常的' /'作为sed命令的分隔符,因为' /'出现在需要匹配的模式中。

答案 3 :(得分:0)

这样的事情可能有用,虽然可能有更好的方法。

sed -E 's/;([0-9])\//;0\1\//;s/\/([0-9])\//\/0\1\//;s/([0-9]*)\/([0-9]*)\/([0-9]*)/\3\1\2/g' your_file > new_file

它执行三个正则表达式替换:第一个找到一位数的月份并且预先设置为0,第二个找到一位数的天数并且预先设置为0,然后第三个执行mm-dd-yyyy到yyyymmdd之间的转换。 / p>

答案 4 :(得分:0)

以下是使用bashdate而不是awk的解决方案。 date实用程序的参数没有很好地标准化,因此我们有Linux和非Linux的替代代码路径(例如Mac等BSD变体)。

test_bash_date

#!/usr/bin/env bash

while IFS=';' read -ra line; do
    line_id=${line[0]}
    if [[ $(uname -s) == Linux ]]; then
        line_date=$(date -d "${line[1]}" +%Y%m%d)
    else
        line_date=$(date -j -f %m/%d/%Y "${line[1]}" +%Y%m%d)
    fi
    echo "$line_id;$line_date"
done < test_file

test_file里面

A345435;3/12/2016
D564565;12/29/2017

输出

> bash test_bash_date 
A345435;20160312
D564565;20171229