grep не работает, когда в функции - PullRequest
0 голосов
/ 11 сентября 2018

У меня есть главный список, master.csv, который выглядит следующим образом:

line1
line2
bill, 1
sonia, 2
rhonda, 3
patty, 4

и список файлов, по которым я хочу отфильтровать:

bill
rhonda

Я хочучтобы сохранить заголовки master.txt, поэтому я делаю head -n 2 master.csv >out.csv && grep -f roster.txt master.txt >>out.csv и получаю:

line1
line2
bill, 1
rhonda, 3

Это здорово, но я должен делать это все время, поэтому я заключаю его в функцию:

filterSections(){
    head -n 2 /dev/stdin && grep -f $1 /dev/stdin
}

Итак, теоретически я могу сделать filterSections roster.txt <master.csv >out.csv, но получаю только:

line1
line2

В моих файлах большего размера, кажется, отсутствует только первая строка.Спасибо

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Проблема в том, что head читает большой кусок данных, а затем записывает только 2 строки.К тому времени, когда grep пытается прочитать из файлового дескриптора, данных не осталось.Это хорошо известная проблема, и встроенная в read оболочка предназначена для ее обработки:

filterSections(){
    read line  # Read all characters up to first newline, and no more
    echo "$line"
    read line  # Read the 2nd line, and no more
    echo "$line"
    grep -f "$1"
}

Обратите внимание, что read и grep по умолчанию считывают из stdin, поэтому в этом нет необходимости.указать /dev/stdin

0 голосов
/ 11 сентября 2018

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

awk -F, 'FNR==NR{seen[$1]; next} FNR <= 2 || $1 in seen' roster.txt master.csv

line1
line2
bill, 1
rhonda, 3

Чтобы поместить это в функцию:

filterSections() {
    awk -F, 'FNR == NR { seen[$1]; next } FNR <= 2 || $1 in seen' "$1" "$2"
}

Назовите это как:

filterSections roster.txt master.csv

объяснение awk:

  • -F,: сделать запятую в качестве разделителя ввода
  • FNR == NR: для первого файла на входе, т.е. roster.txt
  • { seen[$1]; next }: сохранить $1 (1-й столбец) в ассоциативном массиве seen и перейти к следующей записи в том же файле
  • FNR <= 2: когда номер записи второго файла равен <= 2
  • ||: или
  • $1 in seen: 1-й столбец 2-го файла находится в ассоциативном массиве seen

Ссылка:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...