LINUX.ORG.RU

Возможно через bash записать каждую строку из текстового файла в отдельные файлы в зависимости от первого символа строки?

 


1

2

Возможно через bash записать каждую строку из текстового файла в отдельные файлы в зависимости от первого символа строки?

Если строка начинается с ‘a’ - то в файл a_out.txt, если с ‘b’ - в файл b_out.txt и.т.д. Если с цифры - в отдельный файл dig_out.txt, в остальных случаях - в symb_out.txt

В исходном файле имеем:
anton
boris
andre
1igor
_vasilii

После выполнения скрипта:
В файле a_out.txt
anton
andre

В файле b_out.txt
boris

В dig_out.txt
1igor

В symb.out
_vasilii

Если возможно, пожалуйста, подскажите как реализовать это.


Взять строчку, выдрать из неё первую букву, дописать результат в $1_out.txt

Даже sed не нужен.

Aceler ★★★★★ ()
cat source.file | while read line; do

firstsymbol=${line:0:1}

case $firstsymbol in
[a-z]) echo $line >> ${firstsymbol}_out.txt
;;
[0-9]) echo $line >> dig_out.txt
;;
*) echo $line >> symb_out.txt
;;
esac

done
nerve ★★ ()
Ответ на: комментарий от nerve

Круто! …но пока мало что понятно. Но я разберусь. Спасибо.

AlCat ()
Ответ на: комментарий от nerve

cat source.file | while read line; do

Ох. Вот такая конструкция выдаёт так себе понимание bash и вообще системы.

case $firstsymbol in

И таки правильнее case "$firstsymbol" in

vodz ★★★★★ ()
Ответ на: комментарий от ubik

а чем пример выше плох?

В эталонной ненужности: разбазариванию ресурсами, неудобностью в использовании за счёт работы в новом процессе и в котором уже нет далее изначального stdin.

vodz ★★★★★ ()
Ответ на: комментарий от vodz

конструкция выдаёт так себе понимание bash

Ты так говоришь, будто бы Баш вообще можно понять.

anonymous ()
Ответ на: комментарий от vodz

разбазариванию ресурсами

Один лишний процесс для разовой задачи - разбазаривание ресурсов?

неудобностью в использовании за счёт работы в новом процессе

И в чем же неудобство?

Tanger ★★★★★ ()
Ответ на: комментарий от Aceler

Advanced Bash-Scripting Guide

минут на 40

«Вы, наверное, шутите, мистер Фейнман!..»

hobbit ★★★★★ ()
Ответ на: комментарий от Tanger

И в чем же неудобство?

Вот вы посчитали, сколько добавили строк в каждый файл. Цикл у вас закончился, а результаты в переменных были в соседнем процессе.

vodz ★★★★★ ()
Ответ на: комментарий от vodz

правильнее закопать стюардессу и не использовать bash, если на это нет серьёзных причин, конечно (например, стив борн взял в заложники твоего котика)

anonymous ()
Ответ на: комментарий от AlCat

и не надо, если на собеседовании тебя просят что-то написать на баше - безопаснее всего для психики уйти с него

anonymous ()
Ответ на: комментарий от anonymous

правильнее закопать стюардессу

Ну меня то точно bash переживёт. Вопрос то в том, что у хающих как всегда сплошной детский сад, ведь принцип «компьютер железный, и так сойдёт» работает только если код облегчает работу человеку, ему удобнее и нагляднее. Но нет же, нарисуют побольше всяких абсолютно ненужных выкрутасов, которые только усложняют работу, а потом визжат — как сложно.

vodz ★★★★★ ()

Возможно. Составь алгоритм. Он должен быть примерно такой: читать строки построчно, отрезать первый символ каждой строки в переменную или нужное тебе число символов, выводить строку в файл с именем составленным из значения переменной и нужной тебе последовательности символов.

Даже проверок на наличие файла можно не делать.

Реализуй алгоритм на базе, тебе понадобятся: цикл, программа для отрезания части строки, либо сам баш, либо sed, cut, awk.

anonymous ()
Ответ на: комментарий от nerve

Зачем так сложно, автор темы написал, что ему нужно выводить в файл, имя которого будет соответствовать первой букве строки.

Если исходить из этого, то просто:

вывод файла | пока читаем в переменную STR 
делаем
  VAR=`отрезать от STR первый символ`
  вывод $STR > ${VAR}.out.txt
конец

И делов-то.

Как ТЗ составлено так и делай.

infomeh ★★ ()
Последнее исправление: infomeh (всего исправлений: 1)

по-моему такое стоит делать на авк. авк-код можно вместо однострочника положить в файл, и выполнить через awk -f

$ cat input.txt | awk '{ 
    outfile="symb.out";
    if (substr($1,0,1) == "a") { outfile="out_a.txt"};
    if (substr($1,0,1) == "b") { outfile="out_b.txt"};
    if (substr($1,0,1) ~ /[0-9]/) { outfile="dig_out.txt"};
    print $0 > outfile ; 
}'


$ grep -H '' symb.out out_a.txt out_b.txt  dig_out.txt 
symb.out:_vasilii
out_a.txt:anton
out_a.txt:andre
out_b.txt:boris
dig_out.txt:1igor

bl ★★★ ()
Ответ на: комментарий от ubik

Пример выше плох тем, что слишком хорошо читается человеком. Не хватает налёта элитарности баш-хакеров, что ли.

i-rinat ★★★★★ ()
Ответ на: комментарий от X512

Код с cat понятнее. Довольно странно указывать входной файл в конце.

Ну конечно, конечно, у cat то не в конце обрабатываемые файлы то указываются... Вон тут уже появляются cat file | awk, ага, так понятнее, ну да, ну да... Типичный детсад, назло дидам отморожу уши.

vodz ★★★★★ ()
Ответ на: комментарий от vodz

Ну конечно, конечно, у cat то не в конце обрабатываемые файлы то указываются…

Нет конечно, в начале указываются. Сначала cat filename |, а потом куда этот файл выводить.

назло дидам отморожу уши.

ID: 214

Вот уж диды так диды.

X512 ★★★ ()
Последнее исправление: X512 (всего исправлений: 1)
Ответ на: комментарий от X512

Нет конечно,

Виляете. Да и вообще, обрабатываемые файлы — это не часть программы, а вообще-то аргументы программы, как у cat — показать файл человеку, вот единственно разумное применение данной программы, скрипту эта вспомогательная программа в принципе не нужна, url с длинным объяснением по английски, почему это так тут уже приводили выше.

vodz ★★★★★ ()
Ответ на: комментарий от vodz

Важно как выглядит код, а то что cat – это отдельная программа – это незначительная деталь реализации.

Буду везде писать cat <file> | потому что это красивее и понятнее.

X512 ★★★ ()
Последнее исправление: X512 (всего исправлений: 1)
Ответ на: комментарий от nerve

Какой же ты скучный

#!/bin/bash

FILE=$1;

for letter in {a..z}; do
    echo -n '' > "${letter}_out.txt";
done
echo -n '' > "symb.out";
echo -n '' > "dig.out";

for letter in {a..z}; do
    cat $FILE | grep -i "^$letter" >> "${letter}_out.txt";
done

for digit in {0..9}; do
    cat $FILE | grep -i "^$digit" >> "dig.out";
done

cat $FILE | grep -i '[^0-9^a-z]' >> "symb.out";

for letter in {a..z}; do
    if [ ! -s "${letter}_out.txt" ]; then
        rm "${letter}_out.txt";
    fi
done
if [ ! -s "dig.out" ]; then
    rm "dig.out";
fi
if [ ! -s "symb.out" ]; then
    rm "symb.out";
fi

ya-betmen ★★★★★ ()
Ответ на: комментарий от ya-betmen

Какой же ты скучный

Не, когда коту делать нечего, то яйца должны быть до блеска, а у вас массивов не хватает, со статусами файлов, а то удалите пустые, но уже имеющиеся до вызова файлы...

vodz ★★★★★ ()
Ответ на: комментарий от vodz

когда коту делать нечего

Специально поглядел, файл a.txt сделал ровно в 18:00, а в 18:07 запостил комент.

у вас массивов не хватает, со статусами файлов

С массивами я где-то раньше уже какой-то скрипт делал. Уже не интересно.

ya-betmen ★★★★★ ()
Ответ на: комментарий от ya-betmen

Специально поглядел, файл a.txt сделал ровно в 18:00, а в 18:07 запостил комент.

Хотелось бы верить, но с вашим скриптом, обнуляющим всё подряд, про modify time говорить не приходится :)

С массивами я где-то раньше уже какой-то скрипт делал. Уже не интересно.

Не скажите, сколько красивых значков бы добавилось.

vodz ★★★★★ ()
Ответ на: комментарий от ya-betmen

Не всё подряд, в a.txt я данные из оп скопипастил.

Какой же ты скучный

vodz ★★★★★ ()
Ответ на: комментарий от vodz

Ну меня то точно bash переживёт.

это не значит, что нужно им пользоваться

Вопрос то в том, что у хающих как всегда сплошной детский сад, ведь принцип «компьютер железный, и так сойдёт» работает только если код облегчает работу человеку, ему удобнее и нагляднее.

так я о чём твержу! код должен быть удобнее и нагляднее, а не как в bash-е обычно

anonymous ()
Ответ на: комментарий от vodz

солгласен с замечаниями по-поводу

done < file

и

while read -r

однако не ставил себе целью сделать по фен-шую, а просто показал по наитию как вообще можно сделать

nerve ★★ ()
Последнее исправление: nerve (всего исправлений: 1)
Ответ на: комментарий от nerve

солгласен с замечаниями по-поводу

А что не согласны насчёт кавычек для case? Оно же развернет первый символ, если он спецсимвол.

vodz ★★★★★ ()
Ответ на: комментарий от vodz

с переменной в кавычках тоже согласен как бестпрактис.

nerve ★★ ()
Ответ на: комментарий от bl
 printf "kuku\nmumu\n" | awk '{f=substr($1,0,1)"_out.txt"; print $0,"-->",f}'
kuku --> k_out.txt
mumu --> m_out.txt
futurama ★★★★★ ()

Можно так,

#!/usr/bin/env bash
while read -r LINE; do
    first_char="${LINE:0:1}"
    if [[ ${first_char} = [[:alpha:]] ]]; then
        echo "${LINE}" >> "${first_char,,}"_"${2:?}"
    elif [[ ${first_char} = [[:digit:]] ]]; then
        echo "${LINE}" >> "dig_${2:?}"
    else
        echo "${LINE}" >> "symb_${2:?}"
    fi
done < "${1:?}"
# ./script.sh in.text out.text
Breaking ()
Ответ на: комментарий от ashot

незнакомый - это понятно, вопрос в количестве усилий, которые надо приложить, чтобы начать понимать

anonymous ()
Ответ на: комментарий от bl

cat input.txt | awk

За это тоже по рукам указкой.

akk ★★★★★ ()

Вспомнил еще:

При использовании конвейера (пайп), переменные объявленные в цикле, не будут доступны за его пределами.

cat in.text | while read LINE; do
    echo "${LINE}"
    var1="null"
done
echo "$var1"

Если передача идет не через пайп, то переменные доступны:

while read LINE; do
    echo "${LINE}"
    var1="null"
done < in.text
echo "$var1"
Breaking ()
Ответ на: комментарий от ashot

возможно потому, что затраченные усилия того не стоят?

интерактивно есть более удобные оболочки, как язык для скриптования есть гораздо более удобные и читабельные языки, а в каком-нибудь обрезанном эмбеддеде один хрен будет sh/busybox

а ubiquity в 2022 году - слабый аргумент для сетевой операционной системы

anonymous ()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.