Automatinis tekstinių failų apdorojimas ir sujungimas

 

Įvadas

Neseniai man prireikė specifinio scenarijaus, kuris leistų iš įvairių kataloguose esančių tekstinių (.txt) failų surinkti informaciją, sujungti ją į vieną Markdown (.md) failą, surūšiuoti ir pašalinti dublikatus. Ši užduotis reikalavo automatizavimo, kad būtų galima efektyviai apdoroti didelį kiekį duomenų. Todėl parašiau bash skriptą, kuris atliko šią užduotį puikiai.

Kaip veikia scenarijus

Šis scenarijus leidžia vartotojui pasirinkti katalogą iš $HOME aplanko ir pasirinkti, kurie tekstiniai failai turi būti sujungti. Visi pasirinkti failai yra apdorojami, kad būtų surinktos visos eilutės, kurios vėliau yra surūšiuojamos ir pašalinami dublikatai. Galutinis rezultatas yra išsaugomas kaip Markdown failas su tam tikromis metaduomenų žymomis.

Scenarijaus veikimo žingsniai

  1. Katalogo pasirinkimas: Vartotojui pateikiamas sąrašas katalogų, esančių $HOME aplanke. Jei vartotojas nesirenka jokio katalogo ir tiesiog paspaudžia Enter, pasirenkamas numatytasis katalogas ($HOME/Dokumentai).
  2. Tikrinimas, ar katalogas egzistuoja: Patikrinama, ar pasirinktasis katalogas egzistuoja. Jei ne, scenarijus baigia darbą.
  3. Tekstinių failų sąrašo sudarymas: Scenarijus suranda visus .txt failus pasirinktuose kataloguose ir pateikia juos vartotojui su numeracija, kad būtų galima pasirinkti konkrečius failus.
  4. Failų pasirinkimas: Vartotojas gali įvesti numerius, nurodydamas, kurie failai turi būti sujungti. Leidžiama pasirinkti tiek atskirus failus, tiek diapazoną (pvz., 1-5).
  5. Pasirinktų failų apdorojimas: Pasirinkti failai yra atidaromi, jų turinys skaitomas ir visos eilutės surenkamos į vieną sąrašą. Iš šio sąrašo pašalinami dublikatai ir eilutės surūšiuojamos.
  6. Rezultatų išsaugojimas: Surūšiuotos ir unikalios eilutės įrašomos į naują Markdown failą su metaduomenų žymomis (tags: audioknygos, sąrašas). Kiekviena eilutė yra sunumeruojama.

#!/bin/bash
 
# Funkcija diapazono pasirinkimui
select_range() {
    local range_start range_end
    read -p "Įveskite diapazoną (pvz., 1-5) arba atskirus skaičius (pvz., 1 3 5): " selection
 
    # Išvalome galimų pasirinkimų masyvą
    valid_selections=()
 
    for part in $selection; do
        if [[ $part =~ ^([0-9]+)-([0-9]+)$ ]]; then
            range_start=${BASH_REMATCH[1]}
            range_end=${BASH_REMATCH[2]}
            if [ $range_start -ge 0 ] && [ $range_end -lt ${#txt_files[@]} ]; then
                for ((i=range_start; i<=range_end; i++)); do
                    valid_selections+=("$i")
                done
            else
                echo "Netinkamas diapazonas: $part"
            fi
        elif [[ $part =~ ^[0-9]+$ ]] && [ $part -ge 0 ] && [ $part -lt ${#txt_files[@]} ]; then
            valid_selections+=("$part")
        else
            echo "Netinkamas pasirinkimas: $part"
        fi
    done
}
 
# Pasirinkite katalogą pradedantį nuo $HOME/
default_dir="$HOME/Dokumentai"  # Numatytasis katalogas
directories=("$HOME"/*/)
 
echo "Pasirinkite katalogą, pradedantį nuo \$HOME/ (spauskite Enter norėdami pasirinkti $default_dir):"
for i in "${!directories[@]}"; do
    echo "$i) ${directories[$i]}"
done
read -p "> " dir_choice
 
if [ -z "$dir_choice" ]; then
    DIRECTORY="$default_dir"
elif [[ $dir_choice =~ ^[0-9]+$ ]] && [ $dir_choice -ge 0 ] && [ $dir_choice -lt ${#directories[@]} ]; then
    DIRECTORY="${directories[$dir_choice]}"
else
    echo "Netinkamas pasirinkimas."
    exit 1
fi
 
# Patikrinkite, ar katalogas egzistuoja
if [ ! -d "$DIRECTORY" ]; then
    echo "Katalogas $DIRECTORY neegzistuoja"
    exit 1
fi
 
# Gauti visus .txt failus kataloge
txt_files=("$DIRECTORY"/*.txt)
 
# Patikrinkite, ar yra .txt failų
if [ ${#txt_files[@]} -eq 0 ]; then
    echo "Nėra .txt failų kataloge $DIRECTORY"
    exit 1
fi
 
# Atspausdinti failų sąrašą su numeracija
echo "Pasirinkite failus sujungimui (įveskite numerius, atskirtus tarpais arba diapazoną):"
for i in "${!txt_files[@]}"; do
    echo "$i) ${txt_files[$i]}"
done
 
# Nuskaityti vartotojo įvestį
valid_selections=()
select_range
 
# Jei nėra tinkamų pasirinkimų, leisti bandyti dar kartą
while [ ${#valid_selections[@]} -eq 0 ]; do
    select_range
done
 
# Surinkti pasirinktas eilutes
all_lines=()
for i in "${valid_selections[@]}"; do
    while IFS= read -r line; do
        all_lines+=("$line")
    done < "${txt_files[$i]}"
done
 
# Pašalinti dublikatus
mapfile -t uniq_lines < <(printf '%s\n' "${all_lines[@]}" | sort -u)
 
# Surūšiuoti eilutes
IFS=$'\n' sorted_lines=($(sort <<<"${uniq_lines[*]}"))
unset IFS
 
# Pridėti pradines eilutes į naują failą
output_file="$HOME/Obsidian/notes/audioknygos_$(date +%Y%m%d_%H%M%S).md"
{
    echo "---"
    echo "tags:"
    echo " - audioknygos"
    echo " - sąrašas"
    echo "---"
    echo
    # Numeruoti kiekvieną eilutę
    for i in "${!sorted_lines[@]}"; do
        echo "$(($i + 1)). ${sorted_lines[$i]}"
    done
} > "$output_file"
 
echo "Sujungti ir surūšiuoti failai įrašyti į $output_file"

Ką dar būtų galima patobulinti

Nors scenarijus veikia gerai, yra keli dalykai, kuriuos būtų galima patobulinti:

  1. Vartotojo sąsaja: Galima sukurti interaktyvią vartotojo sąsają su dialogų langais, kurie padarytų pasirinkimų procesą patogesnį.
  2. Failų filtravimas: Galima pridėti galimybę filtruoti failus pagal tam tikrus kriterijus, pavyzdžiui, pagal jų dydį ar sukūrimo datą.
  3. Išplėstinis duomenų apdorojimas: Galima pridėti galimybę naudoti sudėtingesnius duomenų apdorojimo algoritmus, tokius kaip natūraliosios kalbos apdorojimas, norint išvalyti ar transformuoti tekstą prieš jį sujungiant.
  4. Lankstesnės išvesties formatavimas: Galima suteikti vartotojui daugiau pasirinkimų, kaip formatuoti išvestį, pavyzdžiui, pasirinkti tarp skirtingų formatų (Markdown, HTML, paprastas tekstas).

Šis scenarijus parodė, kaip galima automatizuoti kasdienes užduotis naudojant bash skriptus, padedant sutaupyti laiko ir pastangų. Tikiuosi, kad šis įrašas ir scenarijus bus naudingi kitiems, susiduriantiems su panašiomis užduotimis!

Komentarai

Populiarūs šio tinklaraščio įrašai

Configuring a NixOS firewall for everyday use

Setting up syncthing as a service on openSUSE and other Linux distributions

Monitoring SFTP server updates with Python