Всегда включайте первую строку в grep - PullRequest
42 голосов
/ 02 апреля 2012

Я часто grep CSV-файлы с именами столбцов в первой строке.Поэтому я хочу, чтобы выходные данные grep всегда включали первую строку (чтобы получить имена столбцов), а также любые строки, соответствующие шаблону grep.Каков наилучший способ сделать это?

Ответы [ 9 ]

45 голосов
/ 02 апреля 2012

sed:

sed '1p;/pattern/!d' input.txt

awk:

awk 'NR==1 || /pattern/' input.txt

grep1:

grep1() { awk -v pattern="${1:?pattern is empty}" 'NR==1 || $0~pattern' "${2:?filename is empty}"; }
9 голосов
/ 02 апреля 2012

grep на самом деле не имеет понятия номера строки, но есть в awk, поэтому вот пример для вывода строк, содержащих «Incoming» - и первую строку, какой бы она ни была:

awk 'NR == 1 || /Incoming/' foo.csv

Youможет сделать сценарий (немного чрезмерно, но).Я сделал файл grep + 1 и поместил его в него:

#!/bin/sh
pattern="$1" ; shift
exec awk 'NR == 1 || /'"$pattern"'/' "$@"

Теперь можно:

./grep+1 Incoming

edit: удалил "{print;}", которыйдействие по умолчанию в awk.

8 голосов
/ 02 апреля 2012

Вы можете использовать sed вместо grep, чтобы сделать это:

sed -n -e '1p' -e '/pattern/p' < $FILE

Тем не менее, первая строка будет напечатана дважды, если она содержит шаблон.*-n указывает sed не печатать каждую строку по умолчанию.
-e '1p' печатает первую строку.
-e '/pattern/p' печатает каждую строку, соответствующую шаблону.

3 голосов
/ 15 января 2016

Это очень общее решение, например, если вы хотите отсортировать файл, сохраняя первую строку на месте. По сути, "пропустите первую строку как есть, затем сделайте все, что я хочу (awk / grep / sort / что угодно) с остальными данными."

Попробуйте это в скрипте, возможно, назвав его keepfirstline (не забудьте chmod +x keepfirstline и поместите его в PATH):

#!/bin/bash
IFS='' read -r JUST1LIINE
printf "%s\n" "$JUST1LIINE"
exec "$@"

Может использоваться следующим образом:

cat your.data.csv | keepfirstline grep SearchTerm > results.with.header.csv

или, возможно, если вы хотите отфильтровать с помощью awk

cat your.data.csv | keepfirstline awk '$1 < 3' > results.with.header.csv

Мне часто нравится сортировать файл, но заголовок остается в первой строке

cat your.data.csv | keepfirstline sort

keepfirstline выполняет заданную команду (grep SearchTerm), но только после чтения и печати первой строки.

2 голосов
/ 21 сентября 2016

Другая опция:

$ cat data.csv | (read line; echo "$line"; grep SEARCH_TERM)

Пример:

$ echo "title\nvalue1\nvalue2\nvalue3" | (read line; echo "$line"; grep value2)

Выход:

title
value2
1 голос
/ 02 апреля 2012

Вы можете включить альтернативное сопоставление с шаблоном для одного из имен столбцов. Если бы столбец назывался COL , это сработало бы:

$ grep -E 'COL|pattern' file.csv
0 голосов
/ 14 июня 2019

Все ответы были правильными.Еще одна идея для ситуаций, когда grep выводит команду (а не файл), включая первую строку, может быть реализована следующим образом; -)

df -h | grep -E '(^Filesystem|/mnt)'  # <<< returns usage of devices, with mountpoint '/mnt/...'
ps aux | grep -E '(^USER|grep)'       # <<< returns all grep-process

Опция -E grep включает ее регулярное выражение-Режим.Строка, которую мы grep использует | и может быть интерпретирована как "или", поэтому мы смотрим в df -выражение для строк:

  • начиная с Filesystem (ведущий '^'в первом подвыражении означает «строка начинается с»)
  • и строки, которые содержат /mnt

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

head -1 <file> && grep ff <file>
0 голосов
/ 07 ноября 2017

Итак, я опубликовал совсем другой короткий ответ некоторое время назад.

Однако, для тех, кто жаждет команды, которая выглядит как grep с точки зрения использования всех одинаковых опций (хотя этот скрипт требует от васиспользуйте длинные опции, если задействован optarg), и можете справиться со странными символами в именах файлов и т. д., и т. д., развлекая это на части.

По сути, это grep, который всегда выдает первую строку.Если вы считаете, что файл без совпадающих строк должен пропустить излучение этой первой строки (заголовка), то это оставлено в качестве упражнения для читателя.Я сохранил как grep+1.

#!/bin/bash
# grep+1 [<option>...] [<regex>] [<file>...]
# Emits the first line of each input and ignores it otherwise.
# For grep options that have optargs, only the --forms will work here.

declare -a files options
regex_seen=false
regex=

double_dash_seen=false
for arg in "$@" ; do
    is_file_or_rx=true
    case "$arg" in
        -*) is_file_or_rx=$double_dash_seen ;;
    esac
    if $is_file_or_rx ; then
        if ! $regex_seen ; then
            regex="$arg"
            regex_seen=true
        else
            files[${#files[*]}]="$arg"     # append the value
        fi
    else
        options[${#options[*]}]="$arg"     # append the value       
    fi
done

# We could either open files all at once in the shell and pass the handles into
# one grep call, but that would limit how many we can process to the fd limit.
# So instead, here's the simpler approach with a series of grep calls

if $regex_seen ; then
    if [ ${#files[@]} -gt 0 ] ; then
        for file in "${files[@]}" ; do
            head -n 1 "$file"
            tail -n +2 "$file" | grep --label="$file" "${options[@]}" "$regex" 
        done
    else
        grep "${options[@]}"   # stdin
    fi
else
    grep "${options[@]}"   # probably --help
fi

#--eof
0 голосов
/ 02 апреля 2012

Просто сделай

head -1 <filename> 

и затем выполнить grep

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