この入力が与えられた場合:
# 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
#
で始まる行とコメントを含まない行をそのままにして、他のすべてのコメントを同じ列に配置する必要があります。
望ましい出力:
# 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
ここに私が今持っているもの:
# 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
やりすぎているような気がします。この問題に取り組むためのより簡単な方法があるはずだと思います。
すべてのコマンドと引数に#
と他の1文字(ASCIIバイト1で指定された文字など)が含まれていない)の場合、追加のセパレータとして他の文字を挿入し、コメントを揃えるにはcolumn
を使用します( this answer を参照)。したがって、次のようになります。
$ 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
空の行を削除しないようにするために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
シェルのみを使用したテキスト処理は少し厄介で、エラーが発生しやすくなる可能性があります(「 シェルループを使用して、不適切な方法と見なされるテキストを処理するのはなぜですか? 」 )。一般に、これらのようなタスクには、その他のプログラミング言語を使用する方が適切です。
Perl -ne 'if (/^([^#]+?)\s*#(.*)$/) { printf("%-16s#%s\n", $1, $2) } else { print }' file
これは、Perlを使用して#
の前のビット(最後のWordと#
の間のスペースを破棄)と後のビットをキャプチャします。一致した場合は、テキストに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
Pythonスクリプトはあなたが望むことをするはずです:
#!/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)
次のように実行します。
python align.py input.txt
次の出力が生成されます。
# 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