Используйте awk для выбора только выбранных строк с одним полем меньше порогового значения из CSV-файла

Это, вероятно, изменилось с новыми версиями GnuPG, так как в настоящее время вы можете сделать это в одном канале:

$ gpg --with-colons --import-options show-only --import --fingerprint < secret.asc | awk -F: '$1 == "fpr" {print $10;}'

Главным изменением правил игры является опция import-options, которая включает фальшивый импорт . Мы просто работаем с файлом, так как он был бы импортирован, но это не так.

Опция --with-colonsгарантирует стабильный и машинный -анализируемый формат, который мы используем в последней awkчасти.

awkпросто печатает 10-й столбец из строки с отпечатком (, который начинается сfpr).

1
01.06.2021, 16:31
2 ответа

Если вы просто хотите отфильтровать все строки, где 4-е поле ниже порогового значения, будет работать следующая команда awk:

awk -F',' -v margin=0.2 'FNR==2 {min=$4} FNR>1&&($4<=(1+margin)*min)' input.csv

или, если вы хотите, чтобы заголовок также отображался в отфильтрованном выводе:

awk -F',' -v margin=0.2 'FNR==2 {min=$4} FNR==1||($4<=(1+margin)*min)' input.csv

Это установит разделитель полей на ,(, но обратите внимание, что ваш файл не является -стандартным CSV, поскольку у вас есть дополнительные пробелы, разделяющие ваши поля ), и вы импортируете переменную marginсо значением 0.2в программу awk.

Внутри программы она установит значение переменной minв значение в 4-м столбце, если мы находимся в строке 2(FNR==2). Затем он будет печатать только текущую строку, если мы находимся в строке 1 (заголовок -, если вы хотите ), или если мы находимся в части данных файла, а 4-е поле меньше, чем 1+marginумножить на минимальное значение.

1
28.07.2021, 11:27

Это довольно многословный сценарий. -Не используйте короткие -сокращения и не печатайте информацию в stderr. Что касается части sh, вы обычно можете добавить параметры для установки значений «Globals» вверху, чтобы вы могли вызывать с параметрами в дополнение к аргументам. т.е.:

my_script --max-factor 0.15 -p 20 --out-file foo.csv *.csv

Итак, путем фильтрации по rescoredи процентам строк. Подробные части, очевидно, могут быть удалены.

#!/bin/sh

# Globals with defaults set
num_lines=0
max_percent_lines=10
max_factor=0.2

fn_in=""
# Default out. Optionally set to another file.
fn_out=/dev/stdout
# As /dev/null to quiet information
fn_err=/dev/stderr

get_num_lines()
{
    num_lines=$(wc -l< "$1")
}
print_filtered()
{
    awk \
    -v num_lines="$num_lines" \
    -v max_percent_lines="$max_percent_lines" \
    -v max_factor="$max_factor" \
    -v fn_err="$fn_err" \
    '
    BEGIN {
        FS=", "
        # Exclude header
        max_line = (1 + num_lines / 100 * max_percent_lines)
        # Truncate
        max_line -= max_line % 1
        printf "Lines       : %d\n",
            num_lines - 1 >>fn_err
        printf "Line Max    : %d (%d%%)\n",
            max_line, max_percent_lines >>fn_err
    }
    NR == 2 {
        max_rescored = ($4 + $4 * max_factor)
        printf "Rescored Max: %f\n", max_rescored >>fn_err
    }
    NR > 1 {
        print $0
    }
    NR >= max_line {
        printf "Max Line    : %d (Exit)\n", max_line >>fn_err
        exit
    }
    $4 >= max_rescored && NR > 2 {
        printf "Max Rescored: %f (Exit)\n", $4 >>fn_err
        exit
    }
    ' "$fn_in" >>"$fn_out"
}

# Here one could loop multiple input files

Параметры командной строки

По запросу в комментариях.

Есть множество способов получить опции. Простейшими были бы позиционные аргументы. Например:

Usage: script percent margin <files...>

Тогда в сценарии можно было бы сказать:

percent=$1
margin=$2
shift
shift
... loop files...

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

Сначала напишите функцию help. Это может быть что-то вроде. (Использование basenameи $0, вероятно, можно обсудить):

print_help() {
    printf "Usage: %s [OPTIONS] <FILES...>\n" "$(basename "$0")"
    printf "\nSome description\n"
    printf "\nOPTIONS\n"
    printf "  -p --percent-lines  V  Print percent of file. Default %s\n" "$max_percent_lines"
    printf "  -r --max-factor     V  Max rescored increase. Default %s\n" "$max_factor"
    printf "  -o --out-file       V  Output file. Default stdout\n"
    printf "  -q --quiet             Silence information\n"
    printf "  -h --help              This help\n"
    printf "  --                     Everything after this is input files\n"
    printf "\nEverything after first unrecognized option is treated as a file.\n"
}

Там, где обычно вызывается print_help >&2as для печати на стандартный вывод, а не на стандартный вывод.

Для helpвыше используйте полустандартный способ. Он не принимает -abcили --foo=123, но каждая опция и аргумент должны быть разделены пробелами.

При желании, без каламбура, ознакомьтесь с такими сообщениями, как

Тогда простой способ для остальной части скрипта,с некоторой наивной проверкой ошибок может быть:


# While not empty
while ! [ -z "$1" ]; do
    case "$1" in
    -h|--help)
        print_help >&2
        exit 1
        ;;
    -p|--percent-lines)
        shift
        max_percent_lines="$1"
        ;;
    -r|--max-factor)
        shift
        max_factor="$1"
        ;;
    -o|--out-file)
        shift
        fn_out="$1"
        ;;
    -q|--quiet)
        fn_err="/dev/null"
        ;;
    --)
        break
        ;;
    *)
        break
        ;;
    esac
    # Next argument
    shift
done

if ! [ -r "$1" ]; then
    printf "Unable to read file: \`%s'\n" "$1" >&2
    exit 1
fi

# Print header from first file
head -n 1 "$1" >>"$fn_out"

for fn_in in "$@"; do
    printf "Processing '%s'\n" "$fn_in" >>"$fn_err"
    if ! [ -r "$1" ]; then
        printf "Unable to read file: \`%s'\n" "$1" >&2
        exit 1
    fi
    get_num_lines
    print_filtered
done

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

1
28.07.2021, 11:27

Теги

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