我在 Linux 机器上有一个包含两列的文本文件:
- 第1列 = id_no(大部分为5位,有的为6位);
- 第 2 列 = Genetic_markers(全部长度为 50674 位);
12345 0102010205
54322 2221110051
123456 1122011510
我想将文件更改为如下所示:
12345 0 1 0 2 0 1 0 2 0 5
54322 2 2 2 1 1 1 0 0 5 1
123456 1 1 2 2 0 1 1 5 1 0
如何更改第一列,使其向右对齐(如数字所示)?
有人可以帮我用最可靠的方法来更改第二列数字之间的空格吗?请解释代码的元素及其作用。
谢谢
和
perl
:使用
-lane
(-n
一次读取输入一条记录,并-e
使用 中的记录运行表达式$_
,-a
因为a
wk 将行拆分为@F
字段,从记录中-l
删除ine 分隔符),其行为类似于。l
perl
awk
在这里,我们使用
printf
空格将第一个字段左填充到 6 的长度,然后用空格将join
第二个字段拆分为其字符组成部分。为了右对齐,您需要找到文件中最长数字的长度,或者只选择一个大数字并使用它。例如,您可以填充 10 个空格:
如果这种方法足够好,您可以执行以下操作:
这里只发生了两件事:
gsub(/./," &",$2);
:gsub
( g lobal sub stitution) 函数将用您提供的任何替换项替换您给它的正则表达式的所有匹配项(这里,我们只给它一个.
含义“任何字符”)。具有&
特殊含义,表示“正则表达式匹配的任何内容”,因此&
作为替换给出的效果是在每个字符之前插入一个空格。最后一个参数是输入,这里我们给它第二个字段$2
。printf "%10d %s\n",$1,$2
:我们用来printf
打印格式化字符串。%10d
意思是“打印我给你的数字并用10个空格填充”,%s
意思是“打印这个字符串”。因此,我们告诉它打印第一个字段填充了 10 个空格,然后打印已被 修改的第二个字段gsub
。如果只需要填充最小值,则需要读取文件两次。首先获取最长的第一个字段的长度:
有了这个,你就可以更具体:
@terdon 和 @StéphaneChazelas 之前的答案很好,但是将两个流解析捆绑在一起(首先获取第 1 列值的最大字符串长度,第二个使用该最大值作为格式化参数)可能会很有趣。根据 @terdon 的答案和符号这样做可以得出:
注意如何:
k=gsub(...)
不需要“k” ,max
用于替换格式*
中的printf "%*d%s\n"...
NR==FNR{...; next}
) 仅与第一个解析相关,而第二个 {...} 命令块仅与第二个解析相关。使用any
awk
和GNUcolumn
(对于-R
):-o' '
如果您真的关心字段之间的空格,请添加:使用Raku(以前称为 Perl_6)
Raku 是 Perl 家族的一种编程语言。上面使用了 Raku 的
-ne
非自动打印逐行标志。默认情况下,该-n
标志会删除行终点的分隔符。然后,您可以print
省略尾随换行符(默认情况下),或put
,这会添加尾随换行符(想象一下put
代表print-using-terminator)。在第一个答案中,该行明确
.split
位于单空格( 的缩写$_.split
)上。在第二个答案中,Raku 的.words
例程用于按空格进行分割。此后,连接andthen
重新加载$_
,以便可以格式化每列以进行输出。第一列(即.[0]
)使用格式化sprintf
,而第二列(即.[1]
)被comb
编辑为单个字符并返回。注意:如果“ID”确实是(十进制)无符号整数,那么在内部
sprintf
您可以使用u
代替d
,如 中所示sprintf("%6u", …)
。输入示例:
示例输出:
注意:为了避免在文件可能包含空行时引发错误,您可以添加
if
条件来删除空行:要保留空行,可以使用 Raku 的三元运算符:
https://docs.raku.org/routine/sprintf
https://docs.raku.org/routine/%3F%3F%20%21%21
https://raku.org