【问题标题】:Bash - split text file in columns by position/indexesBash - 按位置/索引在列中拆分文本文件
【发布时间】:2019-05-09 14:17:59
【问题描述】:

我有一个结构类似于的文本文件:

2013-11-22 eps Ind      2400000.23551544    100.    
2013-11-22 eps Ind      2400000.23551544    100.    
2013-11-22 eps Ind      2400000.23551544    100.    
2013-11-22 HD 217987    2400000.23551544    900.        
2013-11-22 TOI-134      2400000.23551544    900.    
2013-11-22 tau Cet      2400000.23551544    60.     
2013-11-22 BD+01   316  2400000.23551544    300.    
2013-11-22 BD+01   316  2400000.23551544    300.    
2013-11-22 BD+01   316  2400000.23551544    300.    
2013-11-22 BD+01   316  2400000.23551544    300. 

我需要使用 bash 来提取它。我遇到的主要问题是,虽然列是制表符分隔的,但列中的名称可能有制表符或空格,因此使用awk 在某些情况下会给我错误的列。如何按列分隔文本文件,但按索引?所有列的字符宽度都相同——考虑到空格是一个字符。每列都有不同的宽度。

请注意,eps IndHD 217987BD+01 316 都在同一列上。

谢谢 豪尔赫

【问题讨论】:

  • @EdMorton:我认为空格是一个字符,我这样做错了吗?无论如何,我已经更新了我的问题
  • @EdMorton: BD+01 316 只是一个字段。

标签: awk multiple-columns


【解决方案1】:

如果您的输入确实是您所说的固定宽度字段(我假设这就是您所说的 all columns have the same width in characters,而不是所有字段在所有行内和跨行的宽度都相同)然后使用 GNU awk对于 FIELDWIDTHS:

$ cat tst.awk
BEGIN {
    FIELDWIDTHS = "11 13 20 *"
    OFS = ","
}
{
    for (i=1; i<=NF; i++) {
        gsub(/^\s+|\s+$/,"",$i)
        printf "[%d]=\"%s\"%s", i, $i, (i<NF ? OFS : ORS)
    }
}

$ awk -f tst.awk file
[1]="2013-11-22",[2]="eps Ind",[3]="2400000.23551544",[4]="100."
[1]="2013-11-22",[2]="eps Ind",[3]="2400000.23551544",[4]="100."
[1]="2013-11-22",[2]="eps Ind",[3]="2400000.23551544",[4]="100."
[1]="2013-11-22",[2]="HD 217987",[3]="2400000.23551544",[4]="900."
[1]="2013-11-22",[2]="TOI-134",[3]="2400000.23551544",[4]="900."
[1]="2013-11-22",[2]="tau Cet",[3]="2400000.23551544",[4]="60."
[1]="2013-11-22",[2]="BD+01   316",[3]="2400000.23551544",[4]="300."
[1]="2013-11-22",[2]="BD+01   316",[3]="2400000.23551544",[4]="300."
[1]="2013-11-22",[2]="BD+01   316",[3]="2400000.23551544",[4]="300."
[1]="2013-11-22",[2]="BD+01   316",[3]="2400000.23551544",[4]="300."

【讨论】:

  • 看起来很完美,比我预期的还要好,谢谢! :)
  • 不客气。给它几个小时看看你是否得到更好的答案,然后看看stackoverflow.com/help/someone-answers下一步做什么。
  • 如果我想将变量而不是值传递给FIELDWIDTHS 参数怎么办?例如$w1,$w2,$w3,...?我已经尝试了'$w1 $w2 $w3'"$w1 $w2 $w3",我得到了类似invalid FIELDWIDTHS value, near $w1 $w2 $w3'
  • 假设当你说 variables 你的意思是 shell 变量而不是 awk 变量,从脚本中删除设置 FIELDWIDTHS = "11 13 20 *" 然后通过将 awk 调用为 awk -v FIELDWIDTHS="$w1 $w2 $w3 *" -f tst.awk file 在命令行上设置它。请参阅cfajohnson.com/shell/cus-faq-2.html#Q24 了解如何将 shell 变量的值传递给 awk 脚本。
  • 对不起,是的,我是说shell变量。
【解决方案2】:

我建议使用cut 工具将数据拆分为列。

编辑:如果您有可能的标签列中,但有一个固定字段,请使用带有字符位置的cut

cut -c 12-24,45-50 file.txt

【讨论】:

  • OP 说字段可以包含制表符,因此您不能依赖制表符作为字段分隔符 - The main issue I have is that although the columns are tab separated, the names in column might have tabs
  • Heinrich:那是我第一次遇到困难,但正如@EdMorton 指出的那样,我遇到的主要问题是,虽然列是制表符分隔的,但列中的名称可能有制表符。
  • 抱歉,一开始就读多了。相应地进行了编辑。我仍然推荐 cut,但使用-c(或-b)在特定的字符/字节位置分隔,而不是-d 在特定的分隔符处分隔。
  • Heinrich:很酷,这似乎也能解决问题,谢谢! :)
  • Heinrich:与@EdMorton 的方法相比有什么优势/劣势吗?它看起来确实更容易理解......
【解决方案3】:

这是一种使用 Python 的不同方法。一个鲜为人知的秘密是 Python 可以成为出色的文本处理工具。

#!/usr/bin/env python
import csv
import fileinput
import sys

# Write comma-separated values (CSV) to standard output
writer = csv.writer(sys.stdout)

# For each line of the input, split into columns,
# strip off the leading and trailing white spaces,
# then write the output
for line in fileinput.input():
    columns = [
            line[:11].strip(),    # Index 0 to 10
            line[11:24].strip(),  # Index 11 to 23
            line[24:44].strip(),  # Index 24 to 43
            line[44:].strip()     # The rest
    ]
    writer.writerow(columns)

调用脚本

python script.py data.txt

输出

2013-11-22,eps Ind,2400000.23551544,100.
2013-11-22,eps Ind,2400000.23551544,100.
2013-11-22,eps Ind,2400000.23551544,100.
2013-11-22,HD 217987,2400000.23551544,900.
2013-11-22,TOI-134,2400000.23551544,900.
2013-11-22,tau Cet,2400000.23551544,60.
2013-11-22,BD+01   316,2400000.23551544,300.
2013-11-22,BD+01   316,2400000.23551544,300.
2013-11-22,BD+01   316,2400000.23551544,300.
2013-11-22,BD+01   316,2400000.23551544,300.

【讨论】:

  • 谢谢,但在这种特殊情况下,我想要 bash。如果在 python 中,我很可能会使用numpygenfromtxt 为我做所有事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-23
  • 2015-05-05
  • 2021-05-16
  • 1970-01-01
  • 2016-02-11
相关资源
最近更新 更多