如何使用shell转换为日期格式(DDMMMYYYY)?
我在一个文件中有数据,其中一列是日期列,其日期格式如下:
2021-05-10T18:25:00.000+0100
2021-05-14T18:25:00.000+0100
2021-05-19T18:25:00.000+0100
预期输出为:
10 MAY 2021
14 MAY 2021
19 MAY 2021
我尝试过的方法:
while -r read line
do
year=`echo $line | awk '{ print $1 }' `
month=`echo $line | awk '{ print $2 }' `
dt=`echo $line | awk '{ print $3 }' `
v=$dt"-"$month"-"$year
d=date '`$v' | dd-mm-yyyy
echo $d
done < /f/filename.txt
回答
GNU coreutilsdate命令支持您拥有的输入格式,例如:
date -f filename.txt +'%d %b %Y'
date -f filename.txt +'%d %b %Y'
输出:
tr a-z A-Z如果你想要全大写的话,请把它通过管道。
注意:使用 GNU coreutils 8.30 版进行测试。
- @codeholic24: it can be done with e.g. `paste` and `cut`. However, that should probably be asked in a new question with accurate input data
回答
您在尝试中遇到了许多语法和设计问题。
我不特别推荐为此使用 shell;在date可用性和可读性以及性能方面,普通和 Awk 和 Perl 等解决方案的其他答案对于这项特定任务肯定更好。但在某些情况下,您确实想要或需要使用 shell,因此了解正确的语法是什么样的很重要。
根据记录,shell 完全有能力将空格或任何IFS设置的输入行拆分为变量。
你的作业中也有一些奇怪的错别字d。我在这里疯狂地猜测你的实际意思。
while IFS='-T' read -r year month dt _;
do
date -d "$year-$month-$dt" +"%d %b %Y"
done < /f/filename.txt
d=date whatever会将文字字符串分配给date变量d,然后尝试whatever作为命令运行,但可能会失败。但是,当然,创建一个变量只是为了让您可以立即使用echo它只是无用的echo.
date -d是 GNU 变体;在 *BSD(包括 macOS)上,您需要类似的东西date -j -f %Y-%m-%d +"%d %b %Y" 2021-05-28
我不认为strftime提供月份名称的大写版本;如果 SHOUTING 对你很重要,也许管道
done <file | tr a-z A-Z
格式代码%b取决于语言环境;如果您想强制使用英文(或传统)月份名称,请尝试LC_TIME=POSIX date(现在注意我们如何使用我上面解释的语法!)
回答
对于您的样品,请尝试以下操作:
awk -F'[T-]' '
BEGIN{
num=split("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sept,Oct,Nov,Dec",month,",")
}
{
mon=substr($2,2,1)
}
(mon in month){
print $3,month[mon],$1
}
' Input_file
或尝试以下操作:
awk -F'[T-]' '
BEGIN{
num=split("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sept,Oct,Nov,Dec",month,",")
}
($2+0 in month){
print $3,month[$2+0],$1
}
' Input_file
说明:为上面的代码添加详细说明:
awk -F'[T-]' ' ##Starting awk program from here and setting field separator as - OR T here for all Lines.
BEGIN{ ##Starting BEGIN section of this program here.
num=split("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sept,Oct,Nov,Dec",month,",") ##Creating month array here which has month names here.
}
{
mon=substr($2,2,1) ##Creating variable mon, which has sub string of 2nd field with 1st character.
}
(mon in month){ ##Checking if mon is present in month then do following.
print $3,month[mon],$1 ##Printing 3rd field, month value 1st field.
}
' Input_file ##Mentioning Input_file name here.
回答
使用gnu-awk,这可以在一行中完成:
awk '{
print toupper(strftime("%d %b %Y", mktime(gensub(/[-:T]/, " ", "g"))))
}' file
10 MAY 2021
14 MAY 2021
19 MAY 2021
或者没有gensub:
awk -F '[-:T]' '{$1=$1; print toupper(strftime("%d %b %Y", mktime($0)))}' file
回答
另一种方法:
awk -F'[T-]' 'BEGIN{
mon="JanFebMarAprMayJunJulAugSepOctNovDec"
# if need uppercase use below variable
# mon="JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"
}
{
print $3,substr(mon,($2*3)-2,3), $1
}' file
检测结果:
输入:
$ cat file
2021-01-10T18:25:00.000+0100
2021-02-14T18:25:00.000+0100
2021-03-19T18:25:00.000+0100
2021-04-19T18:25:00.000+0100
2021-05-19T18:25:00.000+0100
2021-06-19T18:25:00.000+0100
2021-07-19T18:25:00.000+0100
2021-08-19T18:25:00.000+0100
2021-09-19T18:25:00.000+0100
2021-10-19T18:25:00.000+0100
2021-11-19T18:25:00.000+0100
2021-12-19T18:25:00.000+0100
输出 :
$ awk -F'[T-]' 'BEGIN{mon="JanFebMarAprMayJunJulAugSepOctNovDec"}{print $3,substr(mon,($2*3)-2,3), $1}' file
10 Jan 2021
14 Feb 2021
19 Mar 2021
19 Apr 2021
19 May 2021
19 Jun 2021
19 Jul 2021
19 Aug 2021
19 Sep 2021
19 Oct 2021
19 Nov 2021
19 Dec 2021
回答
与perl:
$ perl -MTime::Piece -lne '$t = Time::Piece->strptime(substr($_,0,10), "%F");
print $t->strftime("%d %b %Y")' ip.txt
10 May 2021
14 May 2021
19 May 2021
substr($_,0,10)将给出前 10 个字符%F相当于%Y-%m-%d%d %b %Y所需的输出格式- 有关文档,请参阅https://perldoc.perl.org/Time::Piece
我使用了两个语句来提高可读性,单语句版本如下所示:
perl -MTime::Piece -lne 'print Time::Piece->strptime(substr($_,0,10), "%F")->strftime("%d %b %Y")'