sed右对齐一组文本

时间:2013-11-03 08:34:05

标签: bash sed

这个问题起源于string pattaren-matching using awk,基本上我们基于正则表达式模式在多个组中分割一行文本,然后仅打印两个组。现在的问题是,我们可以在通过sed打印时对齐一组吗? 下面是一个例子

$cat input.txt
it is line one
it is longggggggg one
itttttttttt is another one

现在

$sed -e 's/\(.*\) \(.*\) \(.*\) \(.*\)/\1 \3/g' input.txt

它会分割并打印第1组和第3组,但输出为

it line
it longggggggg
itttttttttt another

我的问题是我们可以通过sed来完成,以便输出为

it                             line
it                      longggggggg
itttttttttt                 another

我是用awk做到的,但我觉得可以通过sed来完成,但是我无法知道如何获得第二组的长度然后填充正确的数字在小组之间的空间,我愿意接受任何建议尝试。

6 个答案:

答案 0 :(得分:2)

这可能适合你(GNU sed):

sed -r 's/^(.*) .* (.*) .*$/\1 \2/;:a;s/^.{1,40}$/ &/;ta;s/^( *)(\S*)/\2\1/' file

或:

sed -r 's/^(.*) .* (.*) .*$/printf "%-20s%20s" \1 \2/e' file

答案 1 :(得分:1)

您可以在sed中使用循环来实现您想要的效果:

#!/bin/bash
echo 'aa bb cc dd
11 22 33333333 44
ONE TWO THREEEEEEEEE FOUR' | \
sed -e 's/\(.*\) \(.*\) \(.*\) \(.*\)/\1 \3/g' \
-e '/\([^ ]*\) \([^ ]*\)/ { :x ; s/^\(.\{1,19\}\) \(.\{1,19\}\)$/\1  \2/g ; tx }'

两个19控制列的宽度。 :x是一个标签,只要前面的替换成功,就会由tx循环。 (您可以在tx之前添加p;以“调试”它。

答案 2 :(得分:0)

在这种情况下最容易使用awk ...

您也可以使用bash循环来计算空间数,并在所覆盖的行上运行此命令:

while read; do
    # ... calculate $SPACE ...
    echo $REPLY|sed "s/\([^\ ]*\)\ *[^\ ]*\ *\([^\ ]*\)/\1$SPACES\2/g"
done < file

但我更喜欢使用awk来做所有这些(或其他高级shell语言,如Perl,Python,PHP shell模式......)

答案 3 :(得分:0)

TemplateSpace="                                                      "
TemplateSize=${#TemplateSpace}

sed "
# split your group (based on word here but depend on your real need)
s/^ *\(\w\) \(\w\) \(\w\) \(\w\).*$/\1 \3/

# align
s/$/${TemplateSpace}/
s/^\(.\{${TemplateSize}\}\).*$/\1/
s/\(\w\) \(\w\)\( *\)/\1 \3\2/
"

或更简单的避免TemplateSize(内容中没有点)

TemplateSpace="............................................................."

并替换

s/^\(.\{${TemplateSize}\}.*$/\1/ 

通过

s/^\(${TemplateSpace}\).*$/\1/
s/\./ /g

答案 4 :(得分:0)

删除第2列和第4列。在行长度为23个字符的情况下,右对齐结果列2。

sed -e '
 s/[^ ]\+/                       /4;
 s/[^ ]\+//2;
 s/^\(.\{23\}\).*$/\1/;
 s/\(^[^ ]\+[ ]\+\)\([^ ]\+\)\([ ]\+\)/\1\3\2/;
'

或带有扩展正则表达式的gnu sed

sed -r '
 s/\W+\w+\W+(\w+)\W+\w+$/\1                       /;
 s/^(.{23}).*/\1/;
 s/(+\W)(\w+)(\W+)$/\1\3\2/
'

答案 5 :(得分:-2)

这个问题很老,但我喜欢把它看作一个谜题。 虽然我喜欢简洁的循环解决方案,但这里没有循环或shell帮助。

sed -E "s/ \w+ (\w+) \w+$/ \1/;h;s/./ /g;s/$/#                       /;s/( *)#\1//;x;H;x;s/\n//;s/^( *)(\w+)/\2\1/"

或没有扩展正则表达式

sed "s/ .* \(.*\) .*$/ \1/;h;s/./ /g;s/$/#                       /;s/\( *\)#\1//;x;H;x;s/\n//;s/^\( *\)\([^ ]*\)/\2\1/"