Sed / awk:对齐文件中的单词

时间:2017-08-24 15:00:03

标签: linux bash awk sed text-processing

我有一个具有以下结构的文件:

# #################################################################
#   TEXT: MORE TEXT
#   TEXT: MORE TEXT
# #################################################################

___________________________________________________________________
ITEM 1
___________________________________________________________________
PROPERTY1:     VALUE1_1
PROPERTY222:   VALUE2_1
PROPERTY33:    VALUE3_1
PROPERTY4444:  VALUE4_1
PROPERTY55:    VALUE5_1

Description1:  Some text goes here
Description2:  Some text goes here

___________________________________________________________________
ITEM 2
___________________________________________________________________
PROPERTY1:     VALUE1_2
PROPERTY222:   VALUE2_2
PROPERTY33:    VALUE3_2
PROPERTY4444:  VALUE4_2
PROPERTY55:    VALUE5_2

Description1:  Some text goes here
Description2:  Some text goes here

我想使用sed或awk在文件中添加另一个项目:

 sed -i -r "\$a$PROPERTY1:     VALUE1_3" file.txt
 sed -i -r "\$a$PROPERTY2222:     VALUE2_3" file.txt

等。所以我的下一个项目看起来像这样:

___________________________________________________________________
ITEM 3
___________________________________________________________________
PROPERTY1:     VALUE1_3
PROPERTY222:     VALUE2_3
PROPERTY33:     VALUE3_3
PROPERTY4444:     VALUE4_3
PROPERTY55:     VALUE5_3

Description1:  Some text goes here
Description2:  Some text goes here

是锯齿状的。如何将我的值与前一项对齐?我可以在这里看到2个解决方案:

  1. 在将值插入文件时对齐值。
  2. 要按照我的方式将值插入文件,然后将它们对齐。
  3. 命令

    sed -i -r "s|.*:.*|&|g" file.txt
    

    捕获我想要对齐的属性和值,但我无法正确对齐它们,即

    awk '/^.*:.*$/{ printf "%-40s %-70s\n", $1, $2 }' file.txt
    

    它打印出文件,但它包含描述值和标签,如果它们包含空格或短划线,则剪切值。这只是一团糟。

    我根据我在Stack Overflow和一些博客上发现的内容尝试了更多命令,但我没需要什么。

    注意:描述标记的值不是锯齿状的 - 这是因为我以单独的方式将它们写入文件。

    我的命令出了什么问题?我如何实现我的需求?

4 个答案:

答案 0 :(得分:1)

你可以使用gensub和周到的字段分隔符来处理这个问题:

for i in {1..5}; do
    echo $(( 10 ** i )): $i;
done | awk -F ':::' '/^[^:]+:.+/{
    $0 = gensub(/: +/, ":::", $0 );
    key=( $1 ":" );
    printf "%-40s %s\n", key, $2;
}'

相关部分是我们将“:+”替换为“:::”,然后执行printf将其重新组合在一起。

答案 1 :(得分:1)

当您的文件没有标签时,请尝试以下操作:

sed -r 's/: +/:\t/' file.txt | expand -20 

当此方法有效时,将输出重定向到tmp文件并将tmpfile移动到file.txt

答案 2 :(得分:0)

您可以使用\ t来插入标签(而不是空格,这就是为什么会出现锯齿状的'值)

而不是

sed -i -r "\$a$PROPERTY1:     VALUE1_3" file.txt

使用

sed -i -r "\$a$PROPERTY1:\t\tVALUE1_3" file.txt

答案 3 :(得分:0)

您需要做的就是在插入新行时记住现有的缩进,例如:

echo 'PROPERTY732:    VALUE9_8_7' |
awk -v prop="PROPERTY1" -v val="VALUE1_3" '
        match($0,/^PROPERTY[^[:space:]]+[[:space:]]+/) { wid=RLENGTH }
        { print }
        END { printf "%-*s%s\n", wid, prop":", val }
    '
PROPERTY732:    VALUE9_8_7
PROPERTY1:      VALUE1_3

但目前尚不清楚一次添加1行是否合理,或者您添加的所有其他文本来自何处。

以上内容适用于任何UNIX系统上的任何awk。

如果你的“属性”实际上并不是以“属性”一词开头,那么你只需要编辑你的问题以显示更真实的样本输入/输出,并告诉/告诉我们如何区分属性行和描述行,再次,使用awk解决方案将是微不足道的。