我的数据集中包含一长串日期,格式为'DD-MM-YYYY'。对我来说唯一重要的部分是月份,我想重新格式化这些字符串以获得月份的字符串表示,例如将'23 -01-1994'替换为'January'。
在sed或其他一些实用程序中是否有一个简化的原因,用它们的月份等价物替换这些字符串?
答案 0 :(得分:3)
如果你对awk而不是sed没问题,那么效果很好:
awk -F'-' 'BEGIN { split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec", month, " "); } { printf "%s-%s-%s\n", $1, month[int($2)], $3; }'
<强>解释强>
首先,我们将awk的字段分隔符更改为-
字符。这使得位置变量现在包含日,月和年
BEGIN
块在处理第一行之前运行。为简单起见,我们用split
填充month
数组 - 用空格分隔的字符串。
然后,对于每一行输入,我们输出格式为%s-%s-%s
的字符串,其中%s
将填入我们提供的变量。我们必须这样做是因为我们将输入字符串拆分为-
,因此我们需要重新组合它。第一个和第三个字段保持原样,但第二个字段将转换为数字并用作索引以选择月份文本。例如,如果$2
包含07
,我们会将其转换为数字7
并使用与month[7]
对应的Jul
。
答案 1 :(得分:0)
这将是一个很长很长的sed命令:
sed -E -e 's/\d\d-01-\d\d\d\d/January/' \
-e 's/\d\d-02-\d\d\d\d/February/' \
-e 's/\d\d-03-\d\d\d\d/March/' \
-e 's/\d\d-04-\d\d\d\d/April/' \
...
您可以在Unix / Linux中使用sed
命令而不是date
。但要小心。 date
命令在BSD平台上的工作方式完全不同,如Mac和GNU平台,如Linux。
在Mac上:
$ date -j -f '%d-%m-%Y' '23-01-1994' +"%B"
January
答案 2 :(得分:0)
由于您指定了sed
,因此可以使用以下方法构建相应的sed
命令。首先,让我们从定义bash
数组开始:
months=(01 Jan 02 Feb 03 Mar 04 Apr 05 May 06 Jun 07 Jul 08 Aug 09 Sep 10 Oct 11 Nov 12 Dec)
其次,让我们使用所有需要的cmd
命令创建一个shell变量sed
:
printf -v cmd 's/[[:digit:]]{2}-%s-[[:digit:]]{4}/%s/g; ' "${months[@]}"
最后,我们使用sed:
sed -re "$cmd" input_file
举个例子:
$ echo '01-02-2003 01-12-2004' | sed -re "$cmd"
Feb Dec
使用sed
,需要12个替换命令,每个月一个。 printf
命令从months
变量创建全部12。
$ printf -v cmd 's/[[:digit:]]{2}-%s-[[:digit:]]{4}/%s/g; ' "${months[@]}"
$ echo "$cmd"
s/[[:digit:]]{2}-01-[[:digit:]]{4}/Jan/g; s/[[:digit:]]{2}-02-[[:digit:]]{4}/Feb/g; s/[[:digit:]]{2}-03-[[:digit:]]{4}/Mar/g; s/[[:digit:]]{2}-04-[[:digit:]]{4}/Apr/g; s/[[:digit:]]{2}-05-[[:digit:]]{4}/May/g; s/[[:digit:]]{2}-06-[[:digit:]]{4}/Jun/g; s/[[:digit:]]{2}-07-[[:digit:]]{4}/Jul/g; s/[[:digit:]]{2}-08-[[:digit:]]{4}/Aug/g; s/[[:digit:]]{2}-09-[[:digit:]]{4}/Sep/g; s/[[:digit:]]{2}-10-[[:digit:]]{4}/Oct/g; s/[[:digit:]]{2}-11-[[:digit:]]{4}/Nov/g; s/[[:digit:]]{2}-12-[[:digit:]]{4}/Dec/g;
以上是漫长的。让我们随机从列表中取一个替代命令:
s/[[:digit:]]{2}-09-[[:digit:]]{4}/Sep/g;
这会查找任意两位数,然后是-09-
,后跟任意四位数字,并将其替换为字符串Sep
。由于最终的g
,这是在线上找到的每个这样的日期完成的。
请注意[[:digit:]]
的使用。这将匹配我们所处的任何区域中的任何数字。在具有unicode字体的现代世界中,这比旧的[0-9]
形式更可靠。