Распечатайте / найдите первый символ (с НАИМЕНЬШИМ вхождением) в непустой строке, и порядок важен
BASH GNU bash, версия 4.2.46(2)-релиз (x86_64-redhat-linux-gnu)
Дана строка str, которая может хранить только любые нижние, UPPER или только числовые значения.
Как найти первый символ (с НАИМЕНЬШИМ вхождением) в непустой строкеstr
? Задача состоит в том, чтобы напечатать буквуz, если сценарий такой (как можно быстрее, без ошибок, если данные находятся в строке или файле): https://repl.it/@asangal/find1stleastoccurrencecharmaintainorderanyleastsize
или Пример значенийstr
:
str=aa
, вывод должен быть 'a' (поскольку 'a' - единственный символ в строке - встречается 2 раза)
str=aa1
, вывод должен быть '1' (поскольку '1' - это первый символ с наименьшим числом вхождений, равным 1)
str=aa1c1deef
, вывод должен быть 'c' (поскольку 'c' стояла перед 'd' и оба имели 1 как наименьшее количество вхождений 1)
str=abcdeeddAbac
, вывод должен быть 'A' (поскольку 'A' - это первый символ с меньшим числом вхождений, равным 1)
str=abcdeeddAbacA
, вывод должен быть 'a' (поскольку 'a' - это первый символ с меньшим количеством вхождений, равным 2)
str=abcdeeddAbacAabc
, вывод должен быть 'e' (поскольку 'e' - это первый символ с меньшим числом вхождений, равным 2)
Другой пример значения большого размера может быть:
str=axavzzzfdfdsldfnasdlkfjasdlkfjaslkfjasldkfjaslfjlasjkflasdkjfasdlfjasdljfasdkjfgio23yoryoiasyfoiywoerihlkdfhlaskdnkasdnvxcnvjzxkiivhaslyqwoyroiqwyroqwroqwlkasddlkkhaslkfjasdldkfjalsdkfashoqwiyroiqwyroiqwhrkjhajkdfhaslfkhasldkfh
, вывод должен быть 'g' (поскольку 'g' - это первый символ с наименьшим числом вхождений, равным 1)
Ограничения / контекст:
- Значение может быть набором либо ниже, ВЕРХНИЙ или номер
- Строка всегда будет непустой; мы можем пока игнорировать любые символы типа пробела в значении.
- Найдите первую букву ([a-zA-Z0-9]), присутствующую в
str
строка с наименьшим количеством вхождений. - Если возможно, я не хочу использовать какие-либо выражения (например, if-then-else), циклы (For/While) или пользовательские функции. Использование команд, библиотечных функций (если они доступны пользователю из коробки) - это нормально.
PS: Я знаю, что команды системного уровня вызывают все эти вещи за сценой, но я ищу минимальный код, если это возможно, в командной строке, например, $ prompt.
Я попробовал следующую уродливую не однострочную попытку, как указано ниже, здесь у меня есть цикл for,которого я хочу избежать, если это возможно, иsort
команда помогает, но также заставляет меня терять порядок и не покрывает все условия.
Мне не нравится моя текущая попытка, которую я перечислил ниже, но, похоже, я близок.
str="axavzzzfdfdsldfnasdlkfjasdlkfjaslkfjasldkfjaslfjlasjkflasdkjfasdlfjasdljfasdkjfgio23yoryoiasyfoiywoerihlkdfhlaskdnkasdnvxcnvjzxkiivhaslyqwoyroiqwyroqwroqwlkasddlkkhaslkfjasdldkfjalsdkfashoqwiyroiqwyroiqwhrkjhajkdfhaslfkhasldkfh";
for char in $(echo $str | sed "s/\(.\)/\1\n/g" | grep .| tr '\012' ' ');
do
echo -n "$char=$(echo ${str} | sed "s/\(.\)/\1\n/g" | grep . | grep -c $char)";echo;
done | sort -u
Я считаю, что можно достичь того, что я ищу как однострочный (то есть с помощью набора общих команд и каналов Linux |) в BASH; просто хотел забрать себе мозг! Я знаю, что есть лучшие эксперты по оболочке, чем я.
Большинство решений, которые я нашел в Интернете, не поддерживают порядок (что для меня важно) и просто дают максимальное / меньшее количество / количество символов.
6 ответов
ОТВЕТ №4 - решение для использования файла /substr()/ с уменьшенным массивом
После некоторого обсуждения с @AKS и использования постоянно увеличивающегося набора данных (последний тест с использованием файла размером 36 МБ) awk/array
возникла проблема с памятью (например, для большего набора данных различные awk
ответы - до этого момента - требуется 6-8 ГБ ОЗУ).
Моя первая попытка решить проблему с памятью будет состоять в том, чтобы скопировать весь ввод в новую переменную; да, это означает копирование 36 МБ данных вawk
переменной, но это все равно будет намного меньше, чем 6-8 ГБ ОЗУ.
Используя новый (более крупный) набор данных, предоставленный @AKS:
$ str="upvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLPlakjfaldsfpuFHAOOJJADFIASYDOYsggdhuafaismxasidfuasudfoasdufoiasudfoiayioOISYDOIQYORIYOIRYOIYQNOIYFAclamscvjlaivniauppruporupourpoupupovupuadouaouuouaudfaodfpadufuudofupuaspfupipoporqwooPOFPUnmcupauvpaupvouapouqweruuUPOUADUFUAUASDFLKHLP"
$ for i in {1..10}; do str="${str}${str}"; done
$ for i in {1..3}; do str="${str}${str}"; done
$ echo -e "\n\n-- Adding 'z' the only char in this big string blob 'str' variable'\n"
$ str="${str}z"
$ echo $str | wc
1 1 36864002
$ echo "${str}" > newgiga.txt
$ ls -lh newgiga.txt
-rw-r--r--+ 1 xxxxx yyyyy 36M Jun 6 16:55 newgiga.txt
ПРИМЕЧАНИЕ. При создании этих данных все буквы / цифры встречаются более одного раза, кроме буквы.z
(который появляется только один раз и в конце всего набора данных).
И новый / улучшенный awk
решение:
$ time awk '
{ copy = copy $0 # make a copy of our input for later reparsing
len = length($0)
for ( i=1; i<=len; i++ ) { # get a count of occurrences of each letter/number
token = substr($0,i,1)
count[token]++
}
}
END { for ( i in count ) {
if ( min <= 0 )
min = count[i]
else
min = count[i]<min?count[i]:min # find the lowest/minimum count
}
for ( i=1; i<=len; i++ ) { # reparse input looking for first letter with count == min
token = substr(copy,i,1)
if ( min == count[token] ) {
print token, min # print the letter/number and count and
break # break out of our loop
}
}
}
' newgiga.txt
z 1 # as mentioned in the above NOTE => z occurs just once in the dataset
real 0m19.575s # slightly better rate than the previous answer #3 that took 6 secs for 14 MB of data
user 0m19.406s
sys 0m0.171s
ПРИМЕЧАНИЕ. Этот ответ использовал 160 МБ памяти на моей машине (намного лучше, чем 6-8 ГБ в предыдущих ответах), а также работал примерно с той же скоростью, что и раньше.
Пробовал решение, устраняющее copy
переменная и вместо этого обрабатывает входной файл второй раз. Полученные результаты:
- общее использование памяти снизилось на ~30 МБ (до ~130 МБ)
- общее время работы увеличено на ~2 секунды
Итак, компромиссы на самом деле не стоят затраченных усилий.
EDIT2: в случае, если кому-то нужно знать минимальное значение, впервые появившееся символ / целое число и т.д. из всего Input_file, попробуйте выполнить следующее.
awk '
{
num=split($0,array,"")
for(i=1;i<=num;i++){
++count[array[i]]
}
for(j=1;j<=num;j++){
tot_ind[count[array[j]]]=(tot_ind[count[array[j]]]?tot_ind[count[array[j]]] OFS:"")array[j]
}
for(i in count){
min=min<=count[i]?(min?min:count[i]):count[i]
}
}
END{
print "Minimum value found is:" min
split(tot_ind[min],actual," ")
print "All item(s) with same minimum values are:" actual[1]
}
' Input_file
EDIT: поскольку OP получает ошибку, поэтому, несмотря на чтение из переменной, позволяет читать из Input_file, в случае, если OP считывает значения из Input_file, попробуйте выполнить следующее.
awk '
{
delete tot_ind
delete array
delete count
delete actual
min=""
num=split($0,array,"")
for(i=1;i<=num;i++){
++count[array[i]]
}
for(j=1;j<=num;j++){
tot_ind[count[array[j]]]=(tot_ind[count[array[j]]]?tot_ind[count[array[j]]] OFS:"")array[j]
}
for(i in count){
min=min<=count[i]?(min?min:count[i]):count[i]
}
print "Minimum value found is:" min
split(tot_ind[min],actual," ")
print "All item(s) with same minimum values are:" actual[1]
}' Input_file
Explanation: Добавление подробного объяснения вышеизложенного.
awk ' ##Starting awk program from here.
{
num=split($0,array,"") ##Splitting current line into arrray with NULL delimiter.
for(i=1;i<=num;i++){ ##Running loop to run till num here.
++count[array[i]] ##Creating count array with index of valueof array and keep incrementing its value with 1.
}
for(j=1;j<=num;j++){ ##Running for loop till num here.
tot_ind[count[array[j]]]=(tot_ind[count[array[j]]]?tot_ind[count[array[j]]] OFS:"")array[j] ##Creating tot_ind with index of value of count array, this will have all values of minimum number here.
}
for(i in count){ ##Traversing in array count here.
min=min<=count[i]?(min?min:count[i]):count[i] ##Looking to get minimum value by comparing its value to each element.
}
print "Minimum value found is:" min ##Printing Minimum value here.
split(tot_ind[min],actual," ") ##Splitting tot_ind into actual array to get very first element of minimum value out of all values which have same minimum number.
print "All item(s) with same minimum values are:" actual[1] ##Printing very first minimum number here.
}' Input_file ##Mentioning Input_file name here.
Чтобы получить самое первое минимальное значение, которое встречается в Input_file(кстати, с помощью этого решения все элементы, которые имеют одинаковые минимальные значения, также могут быть напечатаны, с небольшими изменениями в последнем операторе печати этого кода). Написано и протестировано в GNUawk
.
str="abcdeeddAbacA"
awk -v str="$str" '
BEGIN{
num=split(str,array,"")
for(i=1;i<=num;i++){
++count[array[i]]
}
for(j=1;j<=num;j++){
tot_ind[count[array[j]]]=(tot_ind[count[array[j]]]?tot_ind[count[array[j]]] OFS:"")array[j]
}
for(i in count){
min=min<=count[i]?(min?min:count[i]):count[i]
}
print "Minimum value found is:" min
split(tot_ind[min],actual," ")
print "All item(s) with same minimum values are:" actual[1]
}'
ДОКАЗАТЕЛЬСТВО концепции: пробежал выше с примерами OP.
./script.ksh aa
Minimum value found is:2
All item(s) with same minimum values are:a
./script.ksh aa1
Minimum value found is:1
All item(s) with same minimum values are:1
./script.ksh aa1c1deef
Minimum value found is:1
All item(s) with same minimum values are:c
./script.ksh abcdeeddAbac
Minimum value found is:1
All item(s) with same minimum values are:A
./script.ksh abcdeeddAbacA
Minimum value found is:2
All item(s) with same minimum values are:a
./script.ksh abcdeeddAbacAabc
Minimum value found is:2
All item(s) with same minimum values are:e
ПРИМЕЧАНИЕ. Я сохранил вышеупомянутое решение в файле сценария и передал образцы входных данных OP в качестве аргумента сценарию, OP мог использовать все, что пожелает, это было сделано, чтобы показать, как он работает.
ОТВЕТ №1 - решение на основе строки / переменной
Предполагая, что желаемая строка хранится в переменной str
, вот один awk
решение:
awk -v str="${str}" '
BEGIN { num = split(str,token,"") # split str into an array of single letter/number elements
for ( i=1; i<=num; i++ ) { # get a count of occurrences of each letter/number
count[token[i]]++
}
min = 10000000
for ( i in count ) {
min = count[i]<min?count[i]:min # keep track of the lowest/minimum count
}
for ( i=1; i<=num; i++ ) { # loop through array of letter/numbers
if ( min == count[token[i]] ) { # for the first letter/number we find where count = min
print token[i], min # print the letter/number and count and
break # then break out of our loop
}
}
}'
Выполнение приведенного выше для разных строк образца:
++++++++++++++++ str = aa
a 2
++++++++++++++++ str = aa1
1 1
++++++++++++++++ str = aa1c1deef
c 1
++++++++++++++++ str = abcdeeddAbac
A 1
++++++++++++++++ str = abcdeeddAbacA
a 2
++++++++++++++++ str = abcdeeddAbacAabc
e 2
++++++++++++++++ str = axavzzzfdfdsldfnasdlkfjasdlkfjaslkfjasldkfjaslfjlasjkflasdkjfasdlfjasdljfasdkjfgio23yoryoiasyfoiywoerihlkdfhlaskdnkasdnvxcnvjzxkiivhaslyqwoyroiqwyroqwroqwlkasddlkkhaslkfjasdldkfjalsdkfashoqwiyroiqwyroiqwhrkjhajkdfhaslfkhasldkfh
g 1
ОТВЕТ №2 - решение на основе файлов / массивов
Глядя на комментарий OP к ответу RavinderSingh13 re: действительно большая строка находится в файле, и предполагая, что имя файла giga.txt
...
Мы сможем внести незначительные изменения в предыдущий awk
решение вроде такого:
awk '
BEGIN { RS = "\0" } # address files with no cr/lf
{ num = split($0,token,"") # split line/$0 into an array of single letter/number elements
for( i=1; i<=num; i++ ) { # get a count of occurrences of each letter/number
all[NR i] = token[i] # token array is for current line/$0 while all array is for entire file
count[token[i]]++
}
}
END { min = 10000000
for ( i in count ) {
min = count[i]<min?count[i]:min # find the lowest/minimum count
}
for ( i in all ) { # loop through array of letter/numbers
if ( min == count[all[i]] ) { # for the first letter/number we find where count = min
print all[i], min # print the letter/number and count and
break # then break out of our loop
}
}
}
' giga.txt
Размещение более длинного str
образец в giga.txt
:
$ cat giga.txt
axavzzzfdfdsldfnasdlkfjasdlkfjaslkfjasldkfjaslfjlasjkflasdkjfasdlfjasdljfasdkjfgio23yoryoiasyfoiywoerihlkdfhlaskdnkasdnvxcnvjzxkiivhaslyqwoyroiqwyroqwroqwlkasddlkkhaslkfjasdldkfjalsdkfashoqwiyroiqwyroiqwhrkjhajkdfhaslfkhasldkfh
Выполнение вышеуказанного awk
решение против giga.txt
дает нам:
$ awk '....' giga.txt
g 1
ОТВЕТ № 3 - решение на основе файла /substr()
OP предоставил дополнительные сведения о том, как создать "большой" файл данных:
$ ls lR / > giga.txt # I hit ^C after ~20 secs
$ sed "s/\(.\)/\1\n/g" giga.txt | grep -o [a-zA-Z0-9] | tr -d '\012' > newgiga.txt # remove all but letters and numbers
Это дало мне файл из 14 миллионов символов (newgiga.txt
).
Я провел несколько тестов по времени вместе с новым awk
решение (см. ниже) против файла с 14 миллионами символов и придумал следующие тайминги:
- 15 секунд с файлом / массивом на основе
awk
решение (см. мой предыдущий ответ - выше) - 25 секунд с OP
sed/grep/echo/uniq/tr/sort
ответ - 4+ минут с RavinderSingh13's
awk
решение (на самом деле нажмите ^C через 4 минуты) - 6 секунд с новым файлом /substr() на основе
awk
решение (см. ниже)
ПРИМЕЧАНИЕ. Все решения работают с моимnewgiga.txt
файл окончательный ответ был письмом Z
(365 случаев).
Заменив split/array
код с серией substr()
звонков и внесения небольших изменений в то, как all
массив проиндексирован, мне удалось сократить время работы предыдущего файла / массива на ~60% на основеawk
решение:
awk '
BEGIN { RS = "\0" }
{ len=length($0)
for( i=1; i<=len; i++ ) { # get a count of occurrences of each letter/number
token=substr($0,i,1)
a++
all[a] = token # token array is for current line/$0 while all array is for entire file
count[token]++
}
}
END { min=10000000
for( i in count ) {
min = count[i]<min?count[i]:min # find the lowest/minimum count
}
for( i in all ) { # loop through array of letter/numbers
if ( min == count[all[i]] ) { # for the first letter/number we find where count = min
print all[i], min # print the letter/number and count and
break # break out of our loop
}
}
}
' newgiga.txt
ПРИМЕЧАНИЕ: Честно говоря, я не ожидалsubstr()
призывает быть быстрее, чем split/array
метод но я предполагаю awk
имеет довольно быстрый встроенный метод для запуска substr()
звонки.
Если файл умещается в памяти:
<file tr -dc '[:alnum:]' | perl -ln0777e 'while (($c=substr $_,0,1) ne q{}) {$n=eval "y/\Q$c\E//d"; $count{$n}=$count{$n}.$c} END{for (sort {$a <=> $b} keys %count) {print substr $count{$_},0,1; exit}}'
Пытаться
grep -o . <<< ${str} | cat -n | sort -k2 | uniq -c -f1 | sort -nr -k1 -k2 | sed 's/.*[ \t]//g;$!d'
Демо:
$str=aa
$grep -o . <<< ${str} | cat -n | sort -k2 | uniq -c -f1 | sort -nr -k1 -k2 | sed 's/.*[ \t]//g;$!d'
a
$str=aa1
$grep -o . <<< ${str} | cat -n | sort -k2 | uniq -c -f1 | sort -nr -k1 -k2 | sed 's/.*[ \t]//g;$!d'
1
$str=aa1c1deef
$grep -o . <<< ${str} | cat -n | sort -k2 | uniq -c -f1 | sort -nr -k1 -k2 | sed 's/.*[ \t]//g;$!d'
c
$str=abcdeeddAbac
$grep -o . <<< ${str} | cat -n | sort -k2 | uniq -c -f1 | sort -nr -k1 -k2 | sed 's/.*[ \t]//g;$!d'
A
$str=abcdeeddAbacA
$grep -o . <<< ${str} | cat -n | sort -k2 | uniq -c -f1 | sort -nr -k1 -k2 | sed 's/.*[ \t]//g;$!d'
e
$str=abcdeeddAbacAabc
$grep -o . <<< ${str} | cat -n | sort -k2 | uniq -c -f1 | sort -nr -k1 -k2 | sed 's/.*[ \t]//g;$!d'
e
$str=axavzzzfdfdsldfnasdlkfjasdlkfjaslkfjasldkfjaslfjlasjkflasdkjfasdlfjasdljfasdkjfgio23yoryoiasyfoiywoerihlkdfhlaskdnkasdnvxcnvjzxkiivhaslyqwoyroiqwyroqwroqwlkasddlkkhaslkfjasdldkfjalsdkfashoqwiyroiqwyroiqwhrkjhajkdfhaslfkhasldkf
$grep -o . <<< ${str} | cat -n | sort -k2 | uniq -c -f1 | sort -nr -k1 -k2 | sed 's/.*[ \t]//g;$!d'
g
$
Изменить: в приведенном ниже случае
str=abcdeeddAbacA, вывод должен быть 'a' (поскольку 'a' - это первый символ с меньшим количеством вхождений, равным 2)
ee
идет раньше a
Хорошо, я думаю, что наконец-то получил (съел 3 миски морковного пудинга в 5 часов утра); Я был мотивирован!! всеми вами.
- Нет
for
петли илиif-then
используемые условные выражения. - Во время операции не создается переменная.
- С помощью
time
перед следующим решением - показывает, что он завершен для самого большого файла, который у меня был менее 1,5 секундreal 0m1.428s
; в то времяawk
решение с использованием файла заняло около 4,5 секунд). - Больше похоже на однострочный (использование только
Linux commands
а также|
трубы).
Любые комментарии приветствуются (если я пропустил какой-либо вариант использования).
$ echo $str | egrep -o . | \
egrep $(echo $str | grep -o [a-zA-Z0-9] | sort | uniq -c | \
grep " $(echo $str | grep -o [a-zA-Z0-9] | sort | uniq -c| sort -n -k1 | head -1 | grep -ow " [0-9][0-9]*") " | \
sed "s/^[ \t][ \t]*//"|cut -d' ' -f2 | tr '\012' '|' | sed "s/.$//") | head -1
Будет выведена только буква (alnum).
Если кто-то хочет увидеть подсчет (вид вне области видимости), он может изменить -f2
к -f1
в приведенной выше команде вырезания.
Вот сценарий: https://repl.it/@asangal/find1stleastoccurrencecharmaintainorderanyleastsize