SED/AWK:在一个文件

问题描述:

我有以下结构的文件对齐的话:SED/AWK:在一个文件

# ################################################################# 
# 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", $1, $2 }' file.txt 

它打印出的文件,但它包含描述值和标签,如果它们包含空格或破折号,则将其剪切。这只是一个大混乱。

我已经尝试了更多的命令,基于我在堆栈溢出和一些博客上找到的内容,但没有做任何我需要的。

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

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

+0

尽管可以使用sed/awk解决这个问题,但使用更强大的工具可能会更容易解决这个问题。您是否考虑过使用正确的数据结构的完整编程语言(例如perl,ruby,C++)来解决您的问题? – Heinrich

+0

@海因里希,我想避免使用完整的编程语言,因为我在bash中有一个几乎完整的脚本,完全符合我的要求,这是它唯一的问题。由于这个问题(并非如此严重),我不希望强迫脚本的用户安装不同语言的编译器或解释器。 – user2738748

当你的文件是没有标签,试试这个:

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

在这个作品中,输出重定向到一个TMPFILE并移动到TMPFILE file.txt

你可以使用\ t插入选项卡(而不是空格这就是为什么你会得到 '锯齿' 值)

,而不是

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

使用

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

使用标签仍然可能导致锯齿状对齐,当一个按键的长度是例如两个选项卡(加上一些空格)长,另一个键是三个选项卡(再加上一些空格)。 – Heinrich

+0

@ M.B。无论我插入制表符还是空格,属性的名称都不相同,所以我总是会得到锯齿值。 – user2738748

您可以使用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将其重新组合。

+0

你正在错误地调用gensub()(你正在用'$ 0'填充“多少个替换项”字段),你不需要字符串连接的parens,你不需要尾随换行符,我无法想象改变':+'到':::'并将FS设置为':::'应该做的不是将FS设置为':+'(谁说':::'不存在于VALUE?)或者只是使用几个sub()。哦,你应该提到它是由于使用'gensub()'而引起的特定于gawk的。 –

所有你需要做插入新线时,如被记现有的压痕:

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。

如果您的“属性”实际上并没有以PROPERTY开头,那么您只需编辑您的问题以显示更加真实的示例输入/输出,并告诉/告诉我们如何区分PROPERTY行和Description行;再一次,这个解决方案对于awk来说是微不足道的。