다음 입력이 주어지면:
# 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
모든 명령과 인수에 #
와 다른 문자(예: 바이트 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
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
답변2
텍스트 처리에 셸만 사용하는 것은 약간 어색하고 오류가 발생하기 쉽습니다("쉘 루프를 사용하여 텍스트를 처리하는 것이 왜 나쁜 습관으로 간주됩니까?"). 이러한 작업에는 다른 프로그래밍 언어를 사용하는 것이 더 나은 경우가 많습니다.
perl -ne 'if (/^([^#]+?)\s*#(.*)$/) { printf("%-16s#%s\n", $1, $2) } else { print }' file
이는 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
답변3
원하는 작업을 수행하는 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