GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Komplexe Textausrichtung in Bash

Wenn alle Ihre Befehle und Argumente # nicht enthalten , und ein weiteres Zeichen (z. B. das ASCII-Zeichen aus Byte 1), können Sie dieses andere Zeichen als zusätzliches Trennzeichen einfügen und column verwenden um die Kommentare auszurichten (siehe diese Antwort). Also so etwas wie:

$ 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

Wenn Ihr column unterstützt -e nicht Um Leerzeilen zu vermeiden, könnten Sie Leerzeilen etwas hinzufügen (z. B. ein Leerzeichen oder das oben verwendete Trennzeichen):

$ 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

Die Textverarbeitung mit der Shell allein ist etwas umständlich und kann fehleranfällig sein (siehe "Warum wird die Verwendung einer Shell-Schleife zur Textverarbeitung als schlechte Praxis angesehen?"). Es ist im Allgemeinen besser, für solche Aufgaben eine andere Programmiersprache zu verwenden.

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

Dies verwendet Perl, um das Bit vor dem # zu erfassen (Verwerfen von Leerzeichen zwischen dem letzten Wort und dem # ) und das bisschen danach. Wenn die Übereinstimmung erfolgreich war, werden 16 Zeichenstellen für den Text zugewiesen und der formatierte Text und Kommentar gedruckt. Wenn der Abgleich nicht erfolgreich war (weil die Zeile leer war oder mit einem # ), wird die Zeile unverändert gedruckt.

# 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

Hier ist ein Python-Skript, das tun sollte, was Sie wollen:

#!/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)

Führen Sie es so aus:

python align.py input.txt

Es erzeugt die folgende Ausgabe:

# 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. Bash-Skript:Prüfen, ob eine Datei eine Textdatei ist?

  2. Eine eingehende Mail von Text/plain zu Text/html ändern?

  3. Text zwischen zwei bestimmten Zeilen extrahieren?

  4. Entfernen Sie leere Zeilen in einer Textdatei mit grep

  5. Textdatei als Befehle in Bash ausführen

Bash Shebang

Bash-Scripting:So schreiben Sie Daten in Textdateien

So drucken Sie doppelte Zeilen in einer Textdatei unter Linux

Wie bearbeite ich vorherige Zeilen in einem mehrzeiligen Befehl in Bash?

Der BASH-Verlauf wird bei jeder Anmeldung auf 500 Zeilen gekürzt

Textdateien mit mehreren Zeilen als Reihe sortieren