使用额外的空格更改不规则标题

使用额外的空格更改不规则标题

我正在处理数据这种晦涩的文件格式:

   SNP  A1  A2   F1 I1 F2 I2 F3 I3
rs0001   A   C   0.02 0.00 1.99

(注意前三个字段周围的空格)

标题很长(500k 条目),我想将其转换为如下内容:

   SNP  A1  A2   F1_I1 F2_I2 F3_I3
rs0001   A   C   0.02 0.00 1.99

...这样无论是否删除不规则的空白,都更容易使用。作为参考,这也是可以接受的,只要它是一致的:

SNP A1 A2 F1_I1 F2_I2 F3_I3
rs0001 A C 0.02 0.00 1.99

有什么方法可以在 Unix/Linux 中重新格式化它吗?谢谢

答案1

您链接到的 plink 文件格式规范包含许多奇怪的细节。

首先,有一些示例,其中“F1 I1”和“F2 I2”清楚地表示两个不同(但相关)列的标题:

    SNP  A1  A2   F1 I1       F2 I2        F3 I3
 rs0001   A   C   0.98 0.02   1.00 0.00    0.00 0.01 
 rs0002   G   A   0.00 1.00   0.00 0.00    0.99 0.01  

Ix但是,您还给出了一个示例,尽管存在标题,但看起来似乎缺少列值:

    SNP  A1  A2   F1 I1 F2 I2 F3 I3
 rs0001   A   C   0.02 0.00 1.99

对我来说,不清楚这个例子是否是错误的,或者数据实际上可以这样格式化。与该选项相关的评论dose1似乎暗示可以使用一列剂量数据,而不是明显正常的两列格式:“剂量数据是 0..1,而不是 0..2 比例”。根据我的直觉,看起来只给出一个值的示例数据的标题混淆了。

如何处理不精确的规范和仅部分符合您对规范的理解的数据总是很困难。您需要决定数据解析器的宽容程度,以便它正确处理具有轻微标题问题的文件,同时仍然标记无效数据。

关于您的实际文件处理问题:如果有一些外部指示器告诉文件是否具有单值或双值剂量数据,我会Ix使用您熟悉的任何脚本或文本处理语言完全删除标题,无论是sedawkperlpython管他呢。

答案2

您可以使用sed以下内容覆盖第一行:

sed -E 's/(F[[:digit:]]+) (I[[:digit:]])/\1_\2/g;q' < file 1<> file

这很有效,因为我们只读取和写入第一行。这只是一件有效的事情,因为我们正在编写的一行与我们所读取的行的长度完全相同。如果Fn和之间可能有多个空格,In并且您只想用一个替换它们_,则无法使用该方法,并且必须重写整个文件,例如:

perl -pi -e 's/(F\d+)\s+(I\d)/${1}_${2}/g if $. == 1' file

这将创建一个新的file作为原始版本的编辑副本。一些sed实现已经-iperl.例如,使用 GNU sed

sed -Ei '1s/(F[[:digit:]]+)\s+(I[[:digit:]])/\1_\2/g' file

也会起作用。对于其他一些sed实现,您需要-i ''.您可能还需要替换\s[[:space:]].

要将一个或多个空白字符的任何序列替换为单个空格,您可以执行以下操作s/[[:space:]]+/ /g(使用perl,您需要添加该-l选项,否则行分隔符(也是空白)将包含在模式空间中并最终被替换带空格)。

请注意,正则表达式匹配不是很严格,如果F<digits> I<digit>在行中的任何位置查找,那么就会在例如中找到它。可以通过以下方式完成更严格的匹配:PAF12 I0therperl

perl -pi -e 's/(?<!\S)(F\d+)\s+(I\d+)(?!\S)/${1}_${2}/g if $. == 1' file

我们使用否定环顾运算符来检查前面和后面的内容是否不是非空白字符。

相关内容