将文本转换为表格形式

将文本转换为表格形式

我有一个具有以下结构的文本文件:

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,它用换行符打印它。

相关内容