我有一个具有以下结构的文本文件:
aaa
bbb
ccc
ddd
eee
fff
1
2
3
4
5
6
1.1
1.2
1.3
1.4
1.5
1.6
ggg
hhh
iii
jjj
kkk
lll
7
8
9
10
11
12
2.1
2.2
2.3
2.4
2.5
2.6
我想要以下表格结构:
aaa 1 1.1
bbb 2 1.2
ccc 3 1.3
ddd 4 1.4
eee 5 1.5
fff 6 1.6
ggg 7 2.1
hhh 8 2.2
iii 9 2.3
jjj 10 2.4
kkk 11 2.5
lll 12 2.6
在此示例中,每列重复该模式 2 次,但实际文件执行更多次并且具有更多字段。
答案1
paste
应该能够完成这项工作。这x.1
是文件的名称
paste <(grep -E '^[[:alpha:]]+$' x.1) \
<(grep -E '^[[:digit:]]+$' x.1) \
<(grep -E '^[[:digit:]]+[.][[:digit:]]+$' x.1)
答案2
你可以这样做:
mkfifo 0 1 2
awk -v RS= '{print > NR%3}' < file & paste 1 2 0
如果其中任何一个都可能出现死锁段落大于管道缓冲区(Linux 上为 64k)。
答案3
考虑四种类型的数据 - 1) 字母、2) 整数、3) 浮点数和 4) 字母数字,以下awk
脚本可以完成这项工作。
/^[a-zA-Z]+$/ {
alphabets[ia++] = $1;
n++;
}
/[a-zA-Z]+[0-9]+[a-zA-Z0-9]*/ || /[0-9]+[a-zA-Z]+[a-zA-Z0-9]*/ {
alphanumerics[an++] = $1;
}
/[0-9]+[.][0-9]+/ {
floats[f++] = $1;
}
/^[0-9]+$/ {
integers[k++] = $1;
}
END {
for (i = 0; i < n; i++) {
print alphabets[i], integers[i], floats[i], alphanumerics[i];
}
}
将上面的代码保存在一个文件中,例如table.awk
,并执行为
awk -f table.awk input_text_file
特别地,上述“数据类型”的块可以以任何顺序出现在输入文件中。使用样本数据和六个字母数字值获得的输出如下:
aaa 1 1.1 a1
bbb 2 1.2 b2
ccc 3 1.3 c3
ddd 4 1.4 d4
eee 5 1.5 e55
fff 6 1.6 6fF
ggg 7 2.1
hhh 8 2.2
iii 9 2.3
jjj 10 2.4
kkk 11 2.5
lll 12 2.6
答案4
使用单个 TXR Lisp 表达式,基于高阶函数和部分应用程序的管道,以及用于格式化固定宽度字段的准文字字符串:
$ txr -e '[(opip (partition* @1 (op where (op equal "")))
(tuples 3)
(reduce-left (op mapcar append))
(apply mapdo (op pprinl `@{1 6} @{2 6} @{3 6}`)))
(get-lines)]' < data
aaa 1 1.1
bbb 2 1.2
ccc 3 1.3
ddd 4 1.4
eee 5 1.5
fff 6 1.6
ggg 7 2.1
hhh 8 2.2
iii 9 2.3
jjj 10 2.4
kkk 11 2.5
lll 12 2.6
怎么运行的
总体来说整个表达有形式[function argument]
。 is ,argument
它(get-lines)
从流中抓取行并返回一个(惰性)字符串列表。流默认为*stdin*
.function
由宏构造,(opip ...)
这就是所有操作发生的地方。
要了解opip
,我们必须知道op
,它opip
使用隐含地:它代表“op
管道”)。此外,op
在一些地方明确使用。简而言之,(op function args ...)
是一个语法糖,用于创建一个匿名函数,该函数调用function
, 并处理一些参数。在 中args ...
,匿名函数的参数可以通过数字引用。匿名函数还隐式地接受尾随参数。例如,(op + 3)
表示一个匿名函数,它将其参数相加,并加上 3。(op - @1 3)
是一个匿名函数,它将其参数减去 3。该语法@1
表示将函数的第一个参数插入到表达式中的给定位置。(op mapcar append)
是一个函数,我们可以向其传递一堆列表,每个列表都包含列表。该函数将按元组获取这些列表并将它们附加在一起。这是用于连接数据的类似粘贴逻辑的基础。
该opip
宏采用一堆表达式并插入op
其中,然后创建一个函数,该函数通过生成的匿名函数传输数据。这是一个简化,但它会做。
(partition* @1 (op where (op equal "")))
equal
通过剪切其元素为空行(空字符串)的列表并删除这些条目,将文件中的原始行列表分解为多个分区。 (名称中partition
没有 的函数*
将保留这些空白)。
(tuples 3)
将这些分区分为 3 组。
这些 3 组或三元组必须并行累积在一起:三元组的第一个元素必须附加到单个列表中,第二个元素必须附加到单个列表中,依此类推。这就是 的工作(reduce-left (op mapcar append))
。核函数(op mapcar append)
被给予一对三元组,并将它们相应的条目连接在一起以创建合并的三元组。这reduce-left
函数通过 this 将三元组列表缩减为单个三元组。
mapdo
然后,这个主三元组在最终表达式中作为调用的参数应用(apply mapdo (op pprinl ...))
。 mapdo
接收一个函数作为其最左边的参数,由(op ...)
再次生成。剩下的参数是巨型三元组的三个元素,代表三列数据。通过匿名函数逐行映射列。
匿名函数采用准文字字符串 中引用的三个参数`@{1 6} @{2 6} @{3 6}`
,其中@{1 6}
means 的@1
字段宽度设置为 6。该字符串准文字插入三个参数(从mapdo
三元组中成对拉出的三个元素)构造一个字符串,其中匿名函数传递给pprinl
,它用换行符打印它。