Как вывести только первое совпадение из каждой строки?

Я нашел хаковый способ сделать это на странице примеров fzf. Это работает с bash 4.3 и perl 5.18:

writecmd () { 
  perl -e 'ioctl STDOUT, 0x5412, $_ for split //, do{ chomp($_ = <>); $_ }' ; 
}

# Example usage
echo 'my test cmd' | writecmd

Он распечатывает команду в stdout, но копирует ее в буфер команд. На связанной странице также есть пример, если вы хотите выполнить команду напрямую.

7
15.03.2017, 12:01
7 ответов
sed -e '
   /\n/{P;d;}
   s/12*3/\n&\n/;D
' < inoutfile
3
27.01.2020, 20:13

Достаточно просто грепа, чтобы в каждой строке были совпадения 123.
Это не имеет смысла, если матч первый, средний или в конце.
Вы просите 123, вы получаете 123, если он находится в строке (если ваш вопрос не выражен неправильно и вам не нужно что-то другое)

$ grep -wo '123' file # -w: word match  -o : return only matched string instead of the whole line (default grep operation)

В случае, если вам нужно поймать с помощью regex первое число каждой строки (любое число - любая длина), то это сделает работу:

cat <<EOF >file1
asd 111 777 aaa wrqiqirw 123
333 123 itiewth 123 asno 123
4444 111 123 123 567
boagii what 666 asdnojaneoienton 123
EOF
grep -Po '^[0-9]+|^.*?\K[0-9]+' file1
#output
111
333
4444
666
4
27.01.2020, 20:13

POSIXLY:

LC_ALL=C sed -e 's/.*\(123\).*/\1/' <file

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

Он также создает одну запись в строке, но соответствует последнему , а не первому .

Для сопоставления первого с GNU sed и PCRE:

LC_ALL=C sed -E 's/.*?(123).*/\1/'

( -E для расширенного RE будет в следующей версии POSIX)

3
27.01.2020, 20:13

В Perl просто

perl -lne 'print $& if /\d+/' inputfile

или из stdin:

echo foo 123 bar 456 doo 789 | perl -lne 'print $& if /\d+/'
123

Регулярное выражение \ d + будет соответствовать любой строке последовательных чисел, а $ & относится к соответствующей строке.

4
27.01.2020, 20:13

С pcregrep с шаблоном вроде 12 * 3 :

pcregrep -o1 '(12*3).*'

С pcregrep или GNU grep -P :

grep -Po '^.*?\K12*3'

( pcregrep работает с байтами, превышающими количество символов, тогда как GNU grep будет работать с символами, как определено в текущей локали (и вам нужно убедиться, что ввод содержит допустимый текст в текущей локали)).

Обратите внимание, что GNU grep не будет ничего печатать, если шаблон соответствует пустой строке.

11
27.01.2020, 20:13

С grep в каждой строке:

while IFS= read -r line; do printf '%s\n' "$line" | grep -o 123 | head -1; done < filename

То есть:

  • Цикл while для проверки каждой строки отдельно.
  • grep -o , чтобы получить только совпадение, а не всю строку с совпадениями.
  • head -1 , чтобы брать только первое совпадение, а не следующие.
2
27.01.2020, 20:13

с awk

re='12*3' awk '{match($0, ENVIRON["re"])}; RSTART{print(substr($0, RSTART, RLENGTH))}' file
2
27.01.2020, 20:13

Теги

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