Групповая команда grep

Ниже ответ после правильного разъяснения вопроса, вот окончательное решение для этого:

awk -F'\n' -v RS='Stanford University' 
    'NR==1 && NR==FNR{for (i=1;i<NF;i++)above[$i]++;next}
     NR==2&&NR==FNR{for (j=2;j<NF;j++)below[$j]++;next} 
     NR==3{for (x=1;x<NF;x++)X2017[$x]++;next}
     NR==4{for (y=2;y<NF;y++)Y2017[$y]++;next} 
END{ for (Z in Y2017) {if (Z in above) print Z>"Ranked-above.txt" }; 
     for (T in X2017) {if (T in below) print T>"Ranked-below.txt" };
}' 2018  2017

На выходе будут два файла с рейтингом -выше.txt и с рейтингом -ниже.txt с ожидаемым результатом.

**Ranked-above.txt**
University of Cambridge

**Ranked-below.txt**

Вы можете искать другие университеты, указав вRS='University NAME HERE'

3
24.10.2019, 13:51
3 ответа

Мне кажется, вы неправильно используете *в регулярном выражении.

Спецификацию (ср. также man -страница grep )утверждает, что

*      The preceding item will be matched zero or more times.

Таким образом, ваше регулярное выражение будет означать :«Совпадение с любым именем файла, начинающимся с чего угодно, кроме буквы s, и это ноль или более раз, а затем ноль или более раз буквы m».

Вместо этого регулярное выражение должно выглядеть так:

ls | grep -E '^[^s][[:alnum:]]*m'

т.е. вы должны указать какой символ должен присутствовать ноль или более раз перед 'm',в вашем случае подойдет любой буквенно-цифровой символ. Если ваши имена файлов могут содержать -или _, замените [[:alnum:]]на [[:print:]].

В крайнем случае, если имя вашего файла может также начинаться с m, регулярное выражение будет

ls | grep -E '(^m|^[^s][[:print:]]*m)'
0
27.01.2020, 21:29

Для этого вам не нужно grep.

printf '%s\n' [!s]*m*

Тестирование:

$ touch small big larger enormous much
$ ls -l
total 0
-rw-r--r--  1 kk  wheel  0 Oct 24 13:20 big
-rw-r--r--  1 kk  wheel  0 Oct 24 13:20 enormous
-rw-r--r--  1 kk  wheel  0 Oct 24 13:20 larger
-rw-r--r--  1 kk  wheel  0 Oct 24 13:20 much
-rw-r--r--  1 kk  wheel  0 Oct 24 13:20 small
$ printf '%s\n' [!s]*m*
enormous

Шаблон подстановки имен файлов [!s]*m*распространяется на все файлы, которые не начинаются с s, но содержат m.

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

Для этого вы можете подбирать файлы, которые не начинаются с mили s, но содержат m, и файлы, которые начинаются с m, отдельно. Это немного сложнее поддерживать, и из чтения кода не сразу понятно, что он делает :

.
$ printf '%s\n' [!ms]*m* m*
enormous
much

Или используйте find, что, ИМХО, легче читать:

$ find. -maxdepth 1 -name '[!s]*' -name '*m*'
./enormous
./much
1
27.01.2020, 21:29

Во-первых, вам не следует анализировать вывод ls. Помимо этого, я собираюсь ответить на ваш вопрос относительно grep.

Если вы настаиваете на использовании grep, то вам нужно следующее:

grep -E "^[a-rt-zA-RT-Z][[:alnum:]]*m" file

На самом деле работает даже без-E:

grep "^[a-rt-zA-RT-Z][[:alnum:]]*m" file 

Это напечатает все, что начинается с чего-либо, кроме sили S, а затем любой буквенно-цифровой символ, который включает m, и любые символы после этого, независимо от того, являются ли они mили нет. По сути, это дает результат, который вы ищете.

Поскольку вы работаете с файлами, первое решение printfвыше намного лучше, так как оно не требует синтаксического анализа ls. Вы можете использовать grepвыше с именами файлов, но я бы не советовал этого и рекомендовал использовать его с содержимым файлов или данных в стандартном выводе.

Вы также можете использовать findдля файлов, так как их не нужно анализировать:

find /path/to/directory -type f -name "*m*" -name "[!s]*"

В зависимости от вашей среды вам может понадобиться выйти из*

find /path/to directory -type f -name "\*m\*" -name "'[!s]\*"
0
27.01.2020, 21:29

Теги

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