remove строка заканчивается определенным расширением в файле

Обработка текста в bash выполняется медленно. Строковые манипуляции с использованием чистого bash подходят для текста, который у вас уже есть в переменных, или для чтения очень маленьких файлов. Я подозреваю, что файлы вычислительной биологии обычно не будут маленькими, поэтому используйте такой инструмент, как awk , который имеет небольшую стоимость запуска, но обрабатывает текст намного быстрее, чем bash.

Предполагая, что вы действительно хотите разделить свой pdb файл:

awk -v RS='\nEND\n' '{ fn="frame" NR ".pdb"; print > fn; close(fn) }' "$filename"

Заставьте awk использовать \ nEND \ n в качестве разделителя входных записей вместо новой строки, тогда вы можете даже использовать его счетчик записей. Разделитель выходной записи по-прежнему используется по умолчанию ORS = "\ n" . (очень приятное предложение Костаса. Я настроил его так, чтобы END должен был быть в начале строки, и добавил close , чтобы убедиться, что он не использует тонну файла- дескрипторы на входах с очень большим количеством конформаций.)

Моя первоначальная идея заключалась в следующем:

awk 'BEGIN{i=0; fn="frame0.pdb"}
     !/^END/ { print > fn; }
     /^END/{ close(fn); fn="frame" ++i ".pdb"; }' \
     "$filename"

awk кэширует дескрипторы файлов, поэтому несколько print> fn не приводят к повторному открытию файла. ( close (fn) делает это. Это делается просто для эффективности, поэтому awk не приводит к загрузке открытых файлов.)

Логика такова: вывести каждую полную строку в текущее имя файла. Когда вы увидите строку END , перейдите к следующему имени файла. Если после последнего END нет другой строки, то новое имя файла никогда не будет записано, и не будет создан рудиментарный последний файл.

OTOH, если вы хотите что-то сделать с массивом строковых блоков в памяти:

# add a `!/^END/` condition to the concat block if you want to avoid a stray newline after each END
awk 'BEGIN{i=0}  
     !/^END/ { arr[i] = arr[i] $0 "\n"; }  # concat onto this array element
     /^END/ { i++; }
     END{for (k in arr) { print arr[k]; > ("frame" k ".pdb") } }' \
"$filename"

Тогда у вас есть awk-массив строк, который вы можете использовать в блоке END . У него хорошие функции регулярных выражений.


Неудачная попытка bash, управляющего sed (nvm, завершается неудачно, потому что sed не читает по одному байту, как оболочка читает ):

i=0
while true; do
    outf="frame${i}.data";
    ##### DON'T USE THIS, sed READS TOO MUCH #####
    strace -o sed.tr sed '/^END/q42' > "$outf";  # strace to see that the 2nd sed invocation finds the file empty
    ret=$?;
    ((i++));
    if [[ $ret == 0 ]];then  # sed didn't see END before EOF
        [[ -s $outf ]] || rm -f "$outf";  # clean up empty last file
        break;
    elif [[ $ret != 42 ]]; then
        echo some other sed error;
        break;
    fi;
done < "$filename"
0
06.12.2017, 12:45
1 ответ

grep раствор:

grep -q '.\.sql$' file.txt && grep -v '\.sql$' file.txt > output_file.txt

Второй grepоператор/команда будет выполняться только в том случае, если первый вернул нулевой статус выхода 0, если найдено какое-либо совпадение с шаблоном .\.sql$


Окончательный output_file.txtконтент:

actual.class
actual1.class
actual2.class
actual3.class
actual4.class
2
28.01.2020, 02:24

Теги

Похожие вопросы