GNU/Linux >> Znalost Linux >  >> Linux

Složité zarovnání textu v bash

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

Linux
  1. Jak odstranit duplicitní řádky uvnitř textového souboru?

  2. Bash Script:Zkontrolujte, zda je soubor textovým souborem?

  3. Upravit příchozí poštu z textu/prostého na text/html?

  1. Extrahovat text mezi dva konkrétní řádky?

  2. Vytiskněte soubor s vynecháním prvních X řádků v Bash

  3. Skript Bash vypíše příkaz Nenalezen na prázdné řádky

  1. Odstraňte prázdné řádky v textovém souboru pomocí grep

  2. Spusťte textový soubor jako příkazy v Bash

  3. echo text s novým řádkem v bash