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

Sed/awk: Aligning words in a file

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

# #################################################################
#   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. 按照我的方式将值插入到文件中,然后对齐它们。

命令

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

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

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

它打印出文件,但它包含描述值和标签,如果包含空格或破折号,则会剪切值。真是一团糟。

我已经根据我在 Stack Overflow 和一些博客上找到的内容尝试了更多命令,但没有一个是我需要的。

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

我的命令有什么问题?我如何实现我所需要的?

您可以使用 \t 插入制表符(而不是空格,这就是您获得 'jagged' 值的原因)

而不是

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

使用

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

您可以使用 gensub 和周到的字段分隔符来解决这个问题:

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

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

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

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

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

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

如果您的 "properties" 实际上不是以 属性 这个词开头,那么您只需要编辑您的问题以显示更真实的示例 input/output 和 tell/show 我们如何区分 属性 行和描述行,同样,使用 awk 解决方案也很简单。

当您的文件没有制表符时,试试这个:

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

当这有效时,将输出重定向到 tmpfile 并将 tmpfile 移动到 file.txt