bash中的复杂文本对齐

Cal*_*leb 6 linux shell scripting bash shell-script

鉴于此输入:

# Lines starting with # stay the same
# Empty lines stay the same
# only lines with comments should change

ls  # show all major directories
              # and other things

cd      # The cd command - change directory  
            # will allow the user to change between file directories

touch             # The touch command, the make file command 
                # allows users to make files using the Linux CLI #  example, cd ~

bar foo baz # foo foo foo
Run Code Online (Sandbox Code Playgroud)

我需要保持以#和开头的行不包含任何评论,但在同一列上对齐所有其他评论。

期望输出:

# Lines starting with # stay the same
# Empty lines stay the same
# Only lines with # in middle should change and be aligned

ls              # show all major directories
                # and other things

cd              # The cd command - change directory  
                # will allow the user to change between file directories

touch           # The touch command, the make file command 
                # allows users to make files using the Linux CLI #  exmaple, cd ~

bar foo baz     # foo foo foo
Run Code Online (Sandbox Code Playgroud)

这是我到目前为止所拥有的:

# Building an array out of input
 while IFS=$'\n' read -r; do 
    lines+=("$REPLY") 
 done 

# Looping through array and selecting elemnts that need change 
for i in "${lines[@]}"
  do
    if  [[ ${i:0:1} == ';' || $i != *";"* ]];
      then
        echo "DOESNT CHANGE: #### $i"
    else 
        echo "HAS TO CHANGE: #### $i"
        array+=( "${i%%";"*}" );
        array2+=("${i##";"}")
    fi
done

# Trying to find the longest line to decide how much space I need to add for each element
max = ${array[0]}

for n in "${array[@]}" ; do
    ((${#n} > max)) && max=${#n}
    echo  "Length:" ${#n} ${n}
done

#Longest line
echo $max

# Loop for populating array 
for j in "${!array2[@]}" ; do
    echo "${array2[j]} " | sed -e "s/;/$(echo "-%20s ;") /g" 
done
Run Code Online (Sandbox Code Playgroud)

我觉得我做得太多了。我认为应该有更简单的方法来解决这个问题。

mur*_*uru 14

如果您的所有命令和参数不包含#, 和一个其他字符(例如字节 1 给出的 ASCII 字符),您可以插入另一个字符作为额外的分隔符并用于column对齐注释(请参阅此答案)。所以,像这样:

$ sed $'s/#/\001#/' input-file | column -ets $'\001'
# Lines starting with # stay the same
# Empty lines stay the same
# only lines with comments should change

ls                                        # show all major directories
                                          # and other things

cd                                        # The cd command - change directory
                                          # will allow the user to change between file directories

touch                                     # The touch command, the make file command
                                          # allows users to make files using the Linux CLI #  example, cd ~

bar foo baz                               # foo foo foo
Run Code Online (Sandbox Code Playgroud)

如果您column不支持-e避免消除空行,则可以在空行中添加一些内容(例如,空格或上面使用的分隔符):

$ sed $'s/#/\001#/;s/^$/\001/' input-file | column -ts $'\001'
# Lines starting with # stay the same
# Empty lines stay the same
# only lines with comments should change

ls                                        # show all major directories
                                          # and other things

cd                                        # The cd command - change directory
                                          # will allow the user to change between file directories

touch                                     # The touch command, the make file command
                                          # allows users to make files using the Linux CLI #  example, cd ~

bar foo baz                               # foo foo foo
Run Code Online (Sandbox Code Playgroud)


Kus*_*nda 5

单独使用 shell 处理文本有点笨拙并且可能容易出错(请参阅“为什么使用 shell 循环处理文本被认为是不好的做法? ”)。对于诸如此类的任务,使用和其他编程语言通常会更好。


perl -ne 'if (/^([^#]+?)\s*#(.*)$/) { printf("%-16s#%s\n", $1, $2) } else { print }' file
Run Code Online (Sandbox Code Playgroud)

这使用 Perl 来捕获前面的位#(丢弃最后一个单词和 之间的空格#)和后面的位。如果匹配成功,它会为文本分配 16 个字符位置并打印格式化文本和注释。如果匹配不成功(因为该行为空白行或以 开头#),则不加修改地打印该行。

# Lines starting with # stay the same
# Empty lines stay the same
# only lines with comments should change

ls              # show all major directories
                # and other things

cd              # The cd command - change directory
                # will allow the user to change between file directories

touch           # The touch command, the make file command
                # allows users to make files using the Linux CLI #  example, cd ~

bar foo baz     # foo foo foo
Run Code Online (Sandbox Code Playgroud)