使用unix复制并替换列

使用unix复制并替换列

我想从文件(.txt)复制第一列,并将其替换为使用 Unix 代码分隔的文本中第二个文件的第一列。

输入文件格式文件1

01/01/2007
02/01/2007
03/01/2007
04/01/2007

文件2

20070101 10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
20070102 10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
20070103 10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
20070104 10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

需要输出

01/01/2007  10.2317   79.1638   6.0  26.7  20.9   0.8  14.0  98.6
02/01/2007  10.2317   79.1638   5.6  26.5  20.8   1.9  13.6  98.0
03/01/2007  10.2317   79.1638   7.5  27.7  20.8   0.1  15.8  96.4
04/01/2007  10.2317   79.1638   8.1  26.0  19.6   0.0  15.5  94.1

答案1

$ cut -d' ' -f 2- file2 | paste file1 -

将从cut中删除第一列file2-f 2-表示“仅输出字段(列)2 及以后”)。其结果将被传递到paste将其内容放入file1第一列中。命令-中的是标准输入(本例中paste为管道)上传递的任何内容的占位符。cut

一步步:

$ cut -d' ' -f 2- file2
10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

$ cut -d' ' -f 2- file2 | paste file1 -
01/01/2007      10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
02/01/2007      10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
03/01/2007      10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
04/01/2007      10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

cut命令需要制表符分隔的输入,但由于我从您的问题中复制并粘贴,因此它是空格分隔的。如果原始数据实际上是制表符分隔的,请-d' 'cut命令中删除 。

默认情况下,该paste命令将在第 1 列和第 2 列之间添加一个选项卡。如果您想要一个空格,请使用paste -d' ' file1 -

另一个问题,有人询问如何使用file2此处已有的日期,并完全删除第一个文件。

我最终得到

$ paste <( date -f <( cut -d ' ' -f 1 file2 ) +"%d/%m/%Y" ) \
        <( cut -d ' ' -f 2- file2 )
01/01/2007      10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
02/01/2007      10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
03/01/2007      10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
04/01/2007      10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

请注意,这需要一个能够理解进程替换 ( ) 的 shell <( ... ),例如bashor ksh,并且还需要 GNU 的date.

可能需要做一些解释:

过程替代<( ... ) 或多或少创建一个临时文件,其中包含括号内命令的输出(实际上是 下的 FIFO /dev/fd)。所以整个命令会经过两步替换:

粘贴 <( 日期 -f剪切输出1+“%d/%m/%Y”)\
      从cut2输出

date -f filename将读取文件中的日期filename并根据给定的格式字符串格式化每个日期。

然后:

粘贴输出日期 从cut2输出

它将把各列粘贴在一起,其中的输出date作为第一列,第二列的输出cut作为其他列。

答案2

根据 awk版本,您可以使用以下方法转换第一列:

awk '{$1=substr($0,7,2)"/"substr($0,5,2)"/"substr($0,1,4); print $0}'  FILE2.csv

例子:

echo "20070101 10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6"  | awk '{$1=substr($0,7,2)"/"substr($0,5,2)"/"substr($0,1,4); print $0}'

返回:

 01/01/2007 10.2317 79.1638 6.0 26.7 20.9 0.8 14.0 98.6

笔记:

第一部分重新定义第一列的值

 $1=substr($0,7,2)"/"substr($0,5,2)"/"substr($0,1,4)

print $0打印整行并重新定义第一列

答案3

您可以使用 awk 来实现此目的:

awk 'NR==FNR{a[++i]=$1;next}{$1=a[++k]; print}' file1 file2

NR==FNR是一个模式含义:{a[++i]=$1;next} 对 file1 中的每条记录(即行)执行。

a[++i]=$1;next方法:将记录的第一个字段(即行)与记录号(即file1的行号)的索引一起保存在数组中,然后读入下一条记录

$1=a[++k]; print方法:将索引为 k 的数组内容复制到当前记录的第一个字段(即行)(始终是 file2 的第 k 条记录(即行))。

相关内容