Как удалить все строки, соответствующие определенному условию

У меня есть несколько файлов pdb, и я хочу сохранить только те строки, которые начинаются с ^FORMUL, и если в строке есть C, а затем число, большее (C3,C4,C5,C6..100 etc), тогда я не должен его печатать. Второе условие состоит в том, что внутри каждой строки сумма C, H and N должна быть не менее 6.

Таким образом, в целом удалите строки, в которых C следует число больше, чем 2> и сумма C+O+N is >= 6.

FORMUL 3 HOH *207(H2 O) (print it) FORMUL 2 SF4 FE4 S4 (print it) FORMUL 3 NIC C5 H7 N O7 (don't print, there is C5) FORMUL 4 HOH *321(H2 O) (print it) FORMUL 3 HEM 2(C34 H32 FE N4 O4) (don't print, there is C34)

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

3
задан 10 January 2018 в 13:07

6 ответов

Хотя он не написан как сценарий оболочки, если кто-то его использует в будущем, вот ответ, как это сделать в Perl.

#!/usr/bin/perl use strict; use warnings; #open ($file, '<', '5PCZ.pdb') or die $!; while (<>) { # read from STDIN a line at a time # Split data on whitespace, but only into three columns my @cols = split /\s+/, $_, 3; next unless $cols[0] eq 'FORMUL'; # Now extract the letter stuff into a hash for easy access. my %letters = m/([A-Z])(\d+)/g; # Give the values we're interested in, a default of 0 $letters{$_} //= 0 for (qw[C O N]); next if $letters{C} > 2 and $letters{C} + $letters{O} + $letters{N} >= 6; # I think we can then print the line; print; }
0
ответ дан 17 July 2018 в 23:27

Вот мое предложение, к сожалению, у меня нет времени, чтобы написать объяснение прямо сейчас:

$ cat script.bash #!/bin/bash INPUT_FILE="${1}" [[ -z "${2}" ]] && OUTPUT_FILE="output-file" || OUTPUT_FILE="${2}" LINE_COUNTER=1 while read -a line; do C_VALUE="$(echo ${line[@]} | grep -Po 'C\d+' | sed 's/C//')" O_VALUE="$(echo ${line[@]} | grep -Po 'O\d+' | sed 's/O//')" H_VALUE="$(echo ${line[@]} | grep -Po 'H\d+' | sed 's/H//')" COH_SUM=$(( C_VALUE + O_VALUE + H_VALUE )) printf '\nLINE=%s: C=%s, O=%s, H=%s, SUM=%s' "$LINE_COUNTER" "$C_VALUE" "$O_VALUE" "$H_VALUE" "$COH_SUM" if [[ "$COH_SUM" -ge "6" ]] || [[ "$C_VALUE" -gt "2" ]]; then LINES_TO_BE_REMOVED="${LINES_TO_BE_REMOVED};${LINE_COUNTER}d" fi ((LINE_COUNTER++)) done < "$INPUT_FILE" printf '\n\nLines to be removed: %s\n\nResult:\n\n' "${LINES_TO_BE_REMOVED#';'}" sed -e "${LINES_TO_BE_REMOVED#';'}" "$INPUT_FILE" | tee "$OUTPUT_FILE"

Как его использовать:

$ cat input-file FORMUL 3 HOH *207(H2 O) FORMUL 2 SF4 FE4 S4 FORMUL 3 NIC C5 H7 N O7 FORMUL 4 HOH *321(H2 O) FORMUL 3 HEM 2(C34 H32 FE N4 O4) $ ./script.bash input-file output-file LINE=1: C=, O=, H=2, SUM=2 LINE=2: C=, O=, H=, SUM=0 ... Lines to be removed: 3d;5d Result: FORMUL 3 HOH *207(H2 O) ... $ cat output-file FORMUL 3 HOH *207(H2 O) FORMUL 2 SF4 FE4 S4 FORMUL 4 HOH *321(H2 O)

Вот просто простой скрипт, который просто выводит строки, которые нужно сохранить:

#!/bin/bash while read -a line; do C_VALUE="$(echo "${line[@]}" | grep -Po 'C\d+')" if [[ ! "${C_VALUE#C}" -gt '2' ]]; then echo "${line[@]}" else O_VALUE="$(echo "${line[@]}" | grep -Po 'O\d+')" H_VALUE="$(echo "${line[@]}" | grep -Po 'H\d+')" C_VALUE="${C_VALUE#C}"; O_VALUE="${O_VALUE#O}"; H_VALUE="${H_VALUE#H}" if (( (( C_VALUE + O_VALUE + H_VALUE )) <= 6 )); then echo "${line[@]}"; fi fi done < "${@}"

Как его использовать:

./script.bash input-file > output-file
3
ответ дан 17 July 2018 в 23:27

Хотя он не написан как сценарий оболочки, если кто-то его использует в будущем, вот ответ, как это сделать в Perl.

#!/usr/bin/perl use strict; use warnings; #open ($file, '<', '5PCZ.pdb') or die $!; while (<>) { # read from STDIN a line at a time # Split data on whitespace, but only into three columns my @cols = split /\s+/, $_, 3; next unless $cols[0] eq 'FORMUL'; # Now extract the letter stuff into a hash for easy access. my %letters = m/([A-Z])(\d+)/g; # Give the values we're interested in, a default of 0 $letters{$_} //= 0 for (qw[C O N]); next if $letters{C} > 2 and $letters{C} + $letters{O} + $letters{N} >= 6; # I think we can then print the line; print; }
0
ответ дан 24 July 2018 в 13:58
  • 1
    Было бы вежливо упомянуть, что это буквальный ответ @DaveCross , размещенный в Stack Overflow . – PerlDuck 10 January 2018 в 19:06
  • 2
    Это действительно мощное решение! Он обрабатывает файл с двумя миллионами строк менее 20 секунд. – pa4080 10 January 2018 в 19:59
  • 3
    @djordje: Опубликовать чужой код , не давая им кредит, немного грубо, не так ли? – Dave Cross 10 January 2018 в 20:35
  • 4
    @djordje: И вы вставили более раннюю версию кода. Я исправил ошибку в более позднем редактировании. – Dave Cross 10 January 2018 в 20:42
  • 5
    Да, я забыл сказать, что все кредиты предоставлены @Dave Cross. Я был немного поспешным, поэтому я действительно забыл, просто хотел помочь другим, которые сталкиваются с подобной проблемой. На самом деле, это не значит, чтобы наложить на меня некоторые кредиты, извините. Это очень мощное решение только в нескольких строках кода. Большое спасибо Дэйву еще раз! Лучший! – djordje 11 January 2018 в 05:28

Вот мое предложение, к сожалению, у меня нет времени, чтобы написать объяснение прямо сейчас:

$ cat script.bash #!/bin/bash INPUT_FILE="${1}" [[ -z "${2}" ]] && OUTPUT_FILE="output-file" || OUTPUT_FILE="${2}" LINE_COUNTER=1 while read -a line; do C_VALUE="$(echo ${line[@]} | grep -Po 'C\d+' | sed 's/C//')" O_VALUE="$(echo ${line[@]} | grep -Po 'O\d+' | sed 's/O//')" H_VALUE="$(echo ${line[@]} | grep -Po 'H\d+' | sed 's/H//')" COH_SUM=$(( C_VALUE + O_VALUE + H_VALUE )) printf '\nLINE=%s: C=%s, O=%s, H=%s, SUM=%s' "$LINE_COUNTER" "$C_VALUE" "$O_VALUE" "$H_VALUE" "$COH_SUM" if [[ "$COH_SUM" -ge "6" ]] || [[ "$C_VALUE" -gt "2" ]]; then LINES_TO_BE_REMOVED="${LINES_TO_BE_REMOVED};${LINE_COUNTER}d" fi ((LINE_COUNTER++)) done < "$INPUT_FILE" printf '\n\nLines to be removed: %s\n\nResult:\n\n' "${LINES_TO_BE_REMOVED#';'}" sed -e "${LINES_TO_BE_REMOVED#';'}" "$INPUT_FILE" | tee "$OUTPUT_FILE"

Как его использовать:

$ cat input-file FORMUL 3 HOH *207(H2 O) FORMUL 2 SF4 FE4 S4 FORMUL 3 NIC C5 H7 N O7 FORMUL 4 HOH *321(H2 O) FORMUL 3 HEM 2(C34 H32 FE N4 O4) $ ./script.bash input-file output-file LINE=1: C=, O=, H=2, SUM=2 LINE=2: C=, O=, H=, SUM=0 ... Lines to be removed: 3d;5d Result: FORMUL 3 HOH *207(H2 O) ... $ cat output-file FORMUL 3 HOH *207(H2 O) FORMUL 2 SF4 FE4 S4 FORMUL 4 HOH *321(H2 O)

Вот просто простой скрипт, который просто выводит строки, которые нужно сохранить:

#!/bin/bash while read -a line; do C_VALUE="$(echo "${line[@]}" | grep -Po 'C\d+')" if [[ ! "${C_VALUE#C}" -gt '2' ]]; then echo "${line[@]}" else O_VALUE="$(echo "${line[@]}" | grep -Po 'O\d+')" H_VALUE="$(echo "${line[@]}" | grep -Po 'H\d+')" C_VALUE="${C_VALUE#C}"; O_VALUE="${O_VALUE#O}"; H_VALUE="${H_VALUE#H}" if (( (( C_VALUE + O_VALUE + H_VALUE )) <= 6 )); then echo "${line[@]}"; fi fi done < "${@}"

Как его использовать:

./script.bash input-file > output-file
3
ответ дан 24 July 2018 в 13:58
  • 1
    Просто увидев начало ответа, сказал мне, что это вы, мило! Новогодние пожелания ... – George Udosen 10 January 2018 в 13:10
  • 2
    Hvala ti Spas, pozdrav - это Srbije. Только один вопрос, когда я запускаю этот скрипт по своим данным, я также получаю эти C34 H32 FE N4 O4, которые немного странны. – djordje 10 January 2018 в 13:31
  • 3
    Привет, @djordje, вы можете загрузить где-то файл данных, чтобы сделать некоторые тесты. Поздрави! – pa4080 10 January 2018 в 14:38
  • 4
    Hey Spas Я справился с этим, написав скрипт в perl. Я могу загрузить его, если вы хотите получить личное удовлетворение, но я думаю, у вас есть более важные вещи: D – djordje 10 January 2018 в 15:24
  • 5
    @djordje, нет, мне это не нужно, если вы решили свою проблему. Рад был помочь! – pa4080 10 January 2018 в 15:33

Хотя он не написан как сценарий оболочки, если кто-то его использует в будущем, вот ответ, как это сделать в Perl.

#!/usr/bin/perl use strict; use warnings; #open ($file, '<', '5PCZ.pdb') or die $!; while (<>) { # read from STDIN a line at a time # Split data on whitespace, but only into three columns my @cols = split /\s+/, $_, 3; next unless $cols[0] eq 'FORMUL'; # Now extract the letter stuff into a hash for easy access. my %letters = m/([A-Z])(\d+)/g; # Give the values we're interested in, a default of 0 $letters{$_} //= 0 for (qw[C O N]); next if $letters{C} > 2 and $letters{C} + $letters{O} + $letters{N} >= 6; # I think we can then print the line; print; }
0
ответ дан 24 July 2018 в 17:02
  • 1
    Было бы вежливо упомянуть, что это буквальный ответ @DaveCross , размещенный в Stack Overflow . – PerlDuck 10 January 2018 в 19:06
  • 2
    Это действительно мощное решение! Он обрабатывает файл с двумя миллионами строк менее 20 секунд. – pa4080 10 January 2018 в 19:59
  • 3
    @djordje: Опубликовать чужой код , не давая им кредит, немного грубо, не так ли? – Dave Cross 10 January 2018 в 20:35
  • 4
    @djordje: И вы вставили более раннюю версию кода. Я исправил ошибку в более позднем редактировании. – Dave Cross 10 January 2018 в 20:42
  • 5
    Да, я забыл сказать, что все кредиты предоставлены @Dave Cross. Я был немного поспешным, поэтому я действительно забыл, просто хотел помочь другим, которые сталкиваются с подобной проблемой. На самом деле, это не значит, чтобы наложить на меня некоторые кредиты, извините. Это очень мощное решение только в нескольких строках кода. Большое спасибо Дэйву еще раз! Лучший! – djordje 11 January 2018 в 05:28

Вот мое предложение, к сожалению, у меня нет времени, чтобы написать объяснение прямо сейчас:

$ cat script.bash #!/bin/bash INPUT_FILE="${1}" [[ -z "${2}" ]] && OUTPUT_FILE="output-file" || OUTPUT_FILE="${2}" LINE_COUNTER=1 while read -a line; do C_VALUE="$(echo ${line[@]} | grep -Po 'C\d+' | sed 's/C//')" O_VALUE="$(echo ${line[@]} | grep -Po 'O\d+' | sed 's/O//')" H_VALUE="$(echo ${line[@]} | grep -Po 'H\d+' | sed 's/H//')" COH_SUM=$(( C_VALUE + O_VALUE + H_VALUE )) printf '\nLINE=%s: C=%s, O=%s, H=%s, SUM=%s' "$LINE_COUNTER" "$C_VALUE" "$O_VALUE" "$H_VALUE" "$COH_SUM" if [[ "$COH_SUM" -ge "6" ]] || [[ "$C_VALUE" -gt "2" ]]; then LINES_TO_BE_REMOVED="${LINES_TO_BE_REMOVED};${LINE_COUNTER}d" fi ((LINE_COUNTER++)) done < "$INPUT_FILE" printf '\n\nLines to be removed: %s\n\nResult:\n\n' "${LINES_TO_BE_REMOVED#';'}" sed -e "${LINES_TO_BE_REMOVED#';'}" "$INPUT_FILE" | tee "$OUTPUT_FILE"

Как его использовать:

$ cat input-file FORMUL 3 HOH *207(H2 O) FORMUL 2 SF4 FE4 S4 FORMUL 3 NIC C5 H7 N O7 FORMUL 4 HOH *321(H2 O) FORMUL 3 HEM 2(C34 H32 FE N4 O4) $ ./script.bash input-file output-file LINE=1: C=, O=, H=2, SUM=2 LINE=2: C=, O=, H=, SUM=0 ... Lines to be removed: 3d;5d Result: FORMUL 3 HOH *207(H2 O) ... $ cat output-file FORMUL 3 HOH *207(H2 O) FORMUL 2 SF4 FE4 S4 FORMUL 4 HOH *321(H2 O)

Вот просто простой скрипт, который просто выводит строки, которые нужно сохранить:

#!/bin/bash while read -a line; do C_VALUE="$(echo "${line[@]}" | grep -Po 'C\d+')" if [[ ! "${C_VALUE#C}" -gt '2' ]]; then echo "${line[@]}" else O_VALUE="$(echo "${line[@]}" | grep -Po 'O\d+')" H_VALUE="$(echo "${line[@]}" | grep -Po 'H\d+')" C_VALUE="${C_VALUE#C}"; O_VALUE="${O_VALUE#O}"; H_VALUE="${H_VALUE#H}" if (( (( C_VALUE + O_VALUE + H_VALUE )) <= 6 )); then echo "${line[@]}"; fi fi done < "${@}"

Как его использовать:

./script.bash input-file > output-file
3
ответ дан 24 July 2018 в 17:02
  • 1
    Просто увидев начало ответа, сказал мне, что это вы, мило! Новогодние пожелания ... – George Udosen 10 January 2018 в 13:10
  • 2
    Hvala ti Spas, pozdrav - это Srbije. Только один вопрос, когда я запускаю этот скрипт по своим данным, я также получаю эти C34 H32 FE N4 O4, которые немного странны. – djordje 10 January 2018 в 13:31
  • 3
    Привет, @djordje, вы можете загрузить где-то файл данных, чтобы сделать некоторые тесты. Поздрави! – pa4080 10 January 2018 в 14:38
  • 4
    Hey Spas Я справился с этим, написав скрипт в perl. Я могу загрузить его, если вы хотите получить личное удовлетворение, но я думаю, у вас есть более важные вещи: D – djordje 10 January 2018 в 15:24
  • 5
    @djordje, нет, мне это не нужно, если вы решили свою проблему. Рад был помочь! – pa4080 10 January 2018 в 15:33

Другие вопросы по тегам:

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