Как распечатать только первое соответствие с grep

Вы могли бы хотеть $HISTIGNORE: "Разделенный от двоеточия список шаблонов раньше решал, какие командные строки должны быть сохранены на списке предыстории". Эта строка в Вашем ~/.bashrc должна сделать задание:

HISTIGNORE='rm *:svn revert*'

Кроме того, можно добавить пространство в начале команды для исключения его из истории. Это работает пока $HISTCONTROL содержит ignorespace или ignoreboth, который является значением по умолчанию на любом дистрибутиве, я использовал.

9
16.10.2015, 18:33
4 ответа

Если Вы действительно хотите возврат просто первое слово и хотите сделать это с grep и Ваш grep оказывается, последняя версия GNU grep, Вы, вероятно, хотите -o опция. Я полагаю, что можно сделать это без -P и \b вначале не действительно необходимо. Следовательно: users | grep -o "^\w*\b".

Все же, как @manatwork упомянутый, встроенная оболочка read или cut/sed/awk кажется, являюсь более соответствующим (особенно, после того как Вы переходите к сути дела, необходимо было бы сделать что-то больше).

6
27.01.2020, 20:03
  • 1
    Альтернативный синтаксис: grep -o "[^ ]*" –  kenorb 16.10.2015, 18:19
  • 2
    @kenorb, который несколько отличается на самом деле (но будет работать в большинстве случаев). –  peterph 17.10.2015, 00:41

Чтобы показать только первое совпадение с grep , используйте параметр -m , например:

grep -m1 pattern file

- m num , - max-count = num

Остановить чтение файла после совпадения числа.

27
27.01.2020, 20:03

Для этого можно использовать массивы bash, например:

arr="(first second third)"
echo ${arr[1]}
-121--38932-

Вот два взаимоисключающих цикла sed :

sed -ne'p;/ 12 * 31 /!d;:n' -e'n;//!bn' <<""
YEAR MONTH DAY RES
1971 1     1   245
1971 1     2   587
...
1971 12    31  685
1971 1     1   245
1971 1     2   587
...
1971 12    31  685
1972 1     1   549
1972 1     2   746
...
1972 12    31  999
1972 1     1   933
1972 1     2   837
...
1972 12    31  343

YEAR MONTH DAY RES
1971 1     1   245
1971 1     2   587
...
1971 12    31  685
1972 1     1   549
1972 1     2   746
...
1972 12    31  999

В основном sed имеет два состояния - p rint и eat . В первом состоянии - p rint state - sed автоматически p печатает каждую входную строку, затем проверяет ее по /12 * 31/ образцы. Если текущее пространство образца равно ! не совпадает с d , и sed тянет в следующей строке ввода и снова запускает сценарий сверху - по команде p rint без попытки выполнить что-либо, что следует за командой d elete вообще.

Если входная строка соответствует /12 * 31/, однако sed попадает во вторую половину сценария - цикл eat . Сначала определяется метка ветви : с именем n ; затем он перезаписывает текущий образец пространство на n ext, а затем сравнивает текущий образец пространство с // последним согласованным образцам. Поскольку строка, которая соответствовала ей ранее, только что была перезаписана с помощью n ext, первая итерация этой eat петли не совпадает, и каждый раз, когда она делает ! не sed b возвращается к метке : n , чтобы получить n ext входную строку и еще раз сравнить ее с // последней соответствующего образца.

При окончательном совпадении - некоторые 365 n ext строки позже - sed автоматически печатает -n ot по завершении сценария, тянет в следующей строке ввода и снова начинает с вершины команды p rint в первом состоянии. Таким образом, каждое состояние цикла будет падать до следующего на тот же ключ и делать как можно меньше в то же время, чтобы найти следующий ключ.

Обратите внимание, что весь сценарий завершается без вызова одной процедуры редактирования и что ему требуется только компиляция одного regexp. Этот результат очень прост - он понимает только и [^ 123] . Более того, по крайней мере половина сравнений, скорее всего, будет выполнена без каких-либо компиляций, потому что единственным адресом, на который ссылается цикл eat , является пустой адрес //. Поэтому sed может полностью завершить этот цикл одним вызовом regexec () для каждой входной линии. sed может также выполнять аналогичные действия для цикла p .


время


Мне было интересно, как различные ответы здесь могут работать, и поэтому я придумал свой собственный стол:

dash <<""
    d=0 D=31 IFS=: set 1970 1
    while   case  "$*:${d#$D}" in (*[!:]) ;;
            ($(($1^($1%4)|(d=0))):1:)
                     D=29 set $1 2;;
            (*:1:)   D=28 set $1 2;;
            (*[3580]:)
                     D=30 set $1 $(($2+1));;
            (*:)     D=31 set $(($1+!(t<730||(t=0)))) $(($2%12+1))
            esac
    do      printf  '%-6d%-4d%-4d%d\n' "$@" $((d+=1)) $((t+=1))
    done|   head    -n1000054 >/tmp/dates

dash <<<''  6.62s user 6.95s system 166% cpu 8.156 total

Это помещает миллион + строк в /tmp/даты и удваивает выход для каждого из 1970 - 3338 лет. Файл выглядит так:

tail -n1465 </tmp/dates | head; echo; tail </tmp/dates

3336  12  27  728
3336  12  28  729
3336  12  29  730
3336  12  30  731
3336  12  31  732
3337  1   1   1
3337  1   2   2
3337  1   3   3
3337  1   4   4
3337  1   5   5

3338  12  22  721
3338  12  23  722
3338  12  24  723
3338  12  25  724
3338  12  26  725
3338  12  27  726
3338  12  28  727
3338  12  29  728
3338  12  30  729
3338  12  31  730

... некоторые из них в любом случае.

И затем я попробовал различные команды на нем:

for  cmd in "sort -uVk1,3" \
            "sed -ne'p;/ 12 * 31 /!d;:n' -e'n;//!bn'" \
            "awk '"'{u=$1 $2 $3 $4;if (!a[u]++) print;}'\'
do   eval   "time ($cmd|wc -l)" </tmp/dates
done

500027
( sort -uVk1,3 | wc -l; ) \
1.85s user 0.11s system 280% cpu 0.698 total

500027
( sed -ne'p;/ 12 * 31 /!d;:n' -e'n;//!bn' | wc -l; ) \
0.64s user 0.09s system 110% cpu 0.659 total

500027
( awk '{u=$1 $2 $3 $4;if (!a[u]++) print;}' | wc -l; ) \
1.46s user 0.15s system 104% cpu 1.536 total

Команды сортировки и sed были выполнены менее чем за половину времени awk - и эти результаты были типичными. Я управлял ими несколько раз. Похоже, все команды также записывают правильное количество строк - и поэтому, вероятно, все они работают.

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

Результаты здесь из стандартного, актуального GNU sed , но я попробовал другой. На самом деле, я попробовал все три команды с другими двоичными файлами, но только команда sed фактически работала с моими инструментами heirloom. Остальные, как я полагаю из-за нестандартного синтаксиса, просто уходят с ошибкой, прежде чем оторваться от земли.

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

PATH=/usr/heirloom/bin/posix2001:$PATH; time ...

500027
( sed -ne'p;/ 12 * 31 /!d;:n' -e'n;//!bn' | wc -l; ) \
0.31s user 0.12s system 136% cpu 0.318 total
-121--96733-

Почему grep ? Для поиска используется команда grep . Вам, кажется, нужно либо вырезать , либо неловко , но читаемый builtin также кажется подходящим.

Сравните их:

users | cut -d' ' -f1
users | sed 's/\s.*//'
users | awk '$0=$1'

Если вы хотите сохранить их в переменной, используйте bash:

read myVar blah < <(users)

или:

read myVar blah <<< $(users). 

Выше ответ на основе @ manatwork comments .

0
27.01.2020, 20:03

это сработало для меня. первый матч поймать с:

users | grep -m 1 "^\b\w*\b"

и последнее совпадение с

users | grep "^\b\w*\b" |tail -1
1
27.01.2020, 20:03

Теги

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