如果有人可以建议我使用命令(sed 或 AWK 单行命令)将文件的每一行分成相等的部分,我会很高兴。例如将每行分成 4 部分。
输入:
ATGCATHLMNPHLNTPLML
输出:
ATGCA THLMN PHLNT PLML
我怀疑 awk 不是最好的工具,但是:
gawk --posix '{ l = sprintf( "%d", 1 + (length()-1)/4);
gsub( ".{"l"}", "& " ) } 1' input-file
如果你有一个 posix 兼容的 awk,你可以省略 --posix,但是 --posix 对于 gnu awk 是必需的,因为这似乎是最常用的实现,我已经给出了 gawk 方面的解决方案。
这应该使用 GNU sed 工作:
sed -r 's/(.{4})/\1 /g'
-r
需要使用扩展正则表达式.{4}
每四个字符捕获一次\1
指的是被括号包围的捕获组,(
)
并在该组后面添加一个空格g
确保在每一行上尽可能多地进行替换一个测试; 这是我终端中的输入和输出:
$ echo "ATGCATHLMNPHLNTPLML" | sed -r 's/(.{4})/\1 /g'
ATGC ATHL MNPH LNTP LML
perl
在这里可能是一个更好的选择:
export cols=4
perl -ne 'chomp; $fw = 1 + int length()/$ENV{cols}; while(/(.{1,$fw})/gm) { print $1 . " " } print "\n"'
这会重新计算每一行的字段宽度。
一个 GNU coreutils 替代方案,field-width 是根据第一行选择的infile
:
cols=4
len=$(( $(head -n1 infile | wc -c) - 1 ))
fw=$(echo "scale=0; 1 + $len / 4" | bc)
cut_arg=$(paste -d- <(seq 1 $fw 19) <(seq $fw $fw $len) | head -c-1 | tr '\n' ',')
的值cut_arg
在上述情况下:
1-5,6-10,11-15,16-
现在将线切割成适当的块:
cut --output-delimiter=' ' -c $cut_arg infile
这可能对您有用(GNU sed):
sed 'h;s/./X/g;s/^\(.*\)\1\1\1/\1 \1 \1 \1/;G;s/\n/&&/;:a;/^\n/bb;/^ /s/ \(.*\n.*\)\n\(.\)/\1 \n\2/;ta;s/^.\(.*\n.*\)\n\(.\)/\1\2\n/;ta;:b;s/\n//g' file
解释:
h
将模式空间 (PS) 复制到保持空间 (HS)s/./X/g
用相同的非空格字符替换 HS 中的每个字符(在这种情况下X
)s/^\(.*\)\1\1\1/\1 \1 \1 \1/
将行分成 4 部分(空格分隔)G
将换行符后跟 HS 的内容附加到 PSs/\n/&&/
将换行符加倍(稍后用作标记):a
引入循环命名空间/^\n/bb
如果我们到达换行符,我们就完成并分支到b
命名空间/^ /s/ \(.*\n.*\)\n\(.\)/\1 \n\2/;ta;
如果第一个字符是空格,则在此时向实行添加一个空格并重复s/^.\(.*\n.*\)\n\(.\)/\1\2\n/;ta
任何其他角色都会碰到并重复:b;s/\n//g
全部完成只需删除标记并打印出结果这项工作适用于任何长度的线,但是该线不能完全被 4 整除,最后一部分也将包含余数。