Фильтрация файла по заданным c элементам в обязательном порядке - PullRequest
1 голос
/ 05 апреля 2020

Я пытаюсь отфильтровать файл по столбцу index и убедиться, что у меня остались некоторые цифры. Столбец index обычно имеет любое число от 0 to 10 в исходном файле (file1.txt).

Файл примера (с черточками внутри, разделяющими каждый чанк):

file1.txt
index age_1  age_2
    0  44      34
    1  10      12
    1  34      44
    2   1      -3
    3   4     -10.3
    3   3.390   4
    4  43       3
    --
    1 -90.3     2
    2  32       3
    3  43     -20
    4   2       2
    --
    0  34      34
    2  21      12
    4  -0.9    12
    --
    4  -2.19   34
    4   4       4
    5   5       -1
    6   4      12
    --
    3  -12      3

Я пытаюсь отфильтровать каждый чанк между тире отдельно и сохранить чанки с диапазоном в столбце index от 1 to 4, где каждый элемент (1,2,3,4) хотя бы один раз присутствует. Таким образом, ожидаемый результат будет выглядеть так:

index age_1  age_2
    1  10      12
    1  34      44
    2   1      -3
    3   4     -10.3
    3   3.390   4
    4  43       3
    --
    1 -90.3     2
    2  32       3
    3  43     -20
    4   2       2

Моя текущая пробная версия просто может проверить диапазон в столбце index, но я не могу указать обязательную фильтрацию:

cat file1.txt | awk -v OFS="\t" '$1=$1' | tail -n +2 | awk '$1>=1 && $1<=4'
1   10  12
1   34  44
2   1   -3
3   4   -10.3
3   3.390   4
4   43  3
1   -90.3   2
2   32  3
3   43  -20
4   2   2
2   21  12
4   -0.9    12
4   -2.19   34
4   4   4
3   -12 3

Я теряю фрагменты, и весь вывод смешивается без указания c фильтрации. Он может просто напечатать любое число в диапазоне от 1 до 4.

Как можно ввести строгую фильтрацию для чисел, присутствующих в столбце Speci c, сохраняя каждый блок отдельно?

Ответы [ 2 ]

3 голосов
/ 05 апреля 2020

Это просто немного другой способ написать решение, которое @ oguzismail уже опубликовало . Мы придумали тот же подход, но он отправил первым. Я проголосовал против его и собирался удалить свой, но в конце концов решил оставить его здесь просто как альтернативный способ реализовать тот же подход (главное отличие - использование мной функции для хранения кода печати) на случай, если кто-то заинтересуется, но он был первым поэтому он должен получить голоса.

$ cat tst.awk
NR==1 { print; next }
($1 >= 1) && ($1 <= 4) {
    rec = rec $0 ORS
    hits[$1]
}
$1 == "--" {
    rec = rec $0 ORS
    prt()
}
END { prt() }

function prt() {
    if ( length(hits) == 4 ) {
        printf "%s", rec
    }
    rec = ""
    delete hits
}

$ awk -f tst.awk file
index age_1  age_2
    1  10      12
    1  34      44
    2   1      -3
    3   4     -10.3
    3   3.390   4
    4  43       3
    --
    1 -90.3     2
    2  32       3
    3  43     -20
    4   2       2
    --
3 голосов
/ 05 апреля 2020

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

$ cat tst.awk
NR == 1 {
  print
  next
}
$1 == "--" {
  if (length(arr) == 4) {
    printf "%s%s", sep, buf
  }
  sep = ($0 ORS)
  buf = ""
  delete arr
}
$1 >= 1 && $1 <= 4 {
  buf = (buf $0 ORS)
  arr[$1]
}
END {
  if (length(arr) == 4) {
    printf "%s%s", sep, buf
  }
}

Это дает:

$ awk -f tst.awk file
index age_1  age_2
    1  10      12
    1  34      44
    2   1      -3
    3   4     -10.3
    3   3.390   4
    4  43       3
    --
    1 -90.3     2
    2  32       3
    3  43     -20
    4   2       2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...