Ниже ответ после правильного разъяснения вопроса, вот окончательное решение для этого:
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'
Мне кажется, вы неправильно используете *
в регулярном выражении.
Спецификацию (ср. также 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)'
Для этого вам не нужно 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
Во-первых, вам не следует анализировать вывод 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]\*"