1

如果有人可以建议我使用命令(sed 或 AWK 单行命令)将文件的每一行分成相等的部分,我会很高兴。例如将每行分成 4 部分。

输入:

ATGCATHLMNPHLNTPLML

输出:

ATGCA THLMN PHLNT PLML
4

4 回答 4

1

我怀疑 awk 不是最好的工具,但是:

gawk --posix '{ l = sprintf( "%d", 1 + (length()-1)/4);
    gsub( ".{"l"}", "& " ) } 1' input-file

如果你有一个 posix 兼容的 awk,你可以省略 --posix,但是 --posix 对于 gnu awk 是必需的,因为这似乎是最常用的实现,我已经给出了 gawk 方面的解决方案。

于 2012-09-27T17:42:39.110 回答
1

这应该使用 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
于 2012-09-27T16:40:38.603 回答
0

perl

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
于 2012-09-27T20:24:53.180 回答
0

这可能对您有用(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 的内容附加到 PS
  • s/\n/&&/将换行符加倍(稍后用作标记)
  • :a引入循环命名空间
  • /^\n/bb如果我们到达换行符,我们就完成并分支到b命名空间
  • /^ /s/ \(.*\n.*\)\n\(.\)/\1 \n\2/;ta;如果第一个字符是空格,则在此时向实行添加一个空格并重复
  • s/^.\(.*\n.*\)\n\(.\)/\1\2\n/;ta任何其他角色都会碰到并重复
  • :b;s/\n//g全部完成只需删除标记并打印出结果

这项工作适用于任何长度的线,但是该线不能完全被 4 整除,最后一部分也将包含余数。

于 2012-09-27T20:35:35.367 回答