Pokud všechny vaše příkazy a argumenty neobsahují #
, a jeden další znak (řekněme znak ASCII daný byte 1), můžete tento další znak vložit jako oddělovač navíc a použít column
pro zarovnání komentářů (viz tato odpověď). Takže něco jako:
$ 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
Pokud je vaše column
nepodporuje -e
abyste se vyhnuli odstranění prázdných řádků, můžete do prázdných řádků něco přidat (například mezeru nebo oddělovací znak použitý výš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
Zpracování textu pomocí samotného shellu je trochu nešikovné a může být náchylné k chybám (viz „Proč je použití shellové smyčky ke zpracování textu považováno za špatný postup?“). Pro úkoly, jako jsou tyto, je obecně lepší použít jiný programovací jazyk.
perl -ne 'if (/^([^#]+?)\s*#(.*)$/) { printf("%-16s#%s\n", $1, $2) } else { print }' file
Toto používá Perl k zachycení bitu před #
(zahození mezer mezi posledním slovem a #
) a kousek po něm. Pokud byla shoda úspěšná, přidělí textu umístění 16 znaků a vytiskne formátovaný text a komentář. Pokud shoda nebyla úspěšná (protože řádek byl prázdný nebo začínal #
), řádek se vytiskne bez úprav.
# 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
Zde je skript Pythonu, který by měl dělat to, co chcete:
#!/usr/bin/env python
# -*- encoding: ascii -*-
"""align.py"""
import re
import sys
# Read the data from the file into a list
lines = []
with open(sys.argv[1], 'r') as textfile:
lines = textfile.readlines()
# Iterate through the data once to get the maximum indentation
max_indentation = 0
comment_block = False
for line in lines:
# Check for the end of a comment block
if comment_block:
if not re.match(r'^\s*#.*$', line):
comment_block = False
# Check for the beginning of a comment block
else:
if re.match(r'^[^#]*[^ #].*#.*$', line):
comment_block = True
indentation = line.index('#')
max_indentation = max(max_indentation, indentation)
# Iterate through the data a second time and output the reformatted text
comment_block = False
for line in lines:
if comment_block:
if re.match(r'^\s*#.*$', line):
line = ' ' * max_indentation + line.lstrip()
else:
comment_block = False
else:
if re.match(r'^[^#]*[^ #].*#.*$', line):
pre, sep, suf = line.partition('#')
line = pre.ljust(max_indentation) + sep + suf
comment_block = True
sys.stdout.write(line)
Spusťte to takto:
python align.py input.txt
Vytváří následující výstup:
# 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