0

BASH GNU bash,版本4.2.46 (2)-release (x86_64-redhat-linux-gnu)

给定一个字符串str,它只能存储任何较低的、UPPER 或数字值。

如何在非空字符串中找到第一个字符(出现次数最少)?问题的重点是在脚本是这样的情况下打印字母' z '(尽可能快,如果数据在字符串或文件中,则不会出现任何错误):https ://repl.it/@asangal/ find1stleastoccurrencecharmaintainorderanyleastsizestr



或示例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的字符)



约束/上下文:

  1. 可以是一组lowerUPPERNumber
  2. 字符串总是非空的;我们现在可以忽略值中的任何空格类型字符。
  3. 找到字符串中出现次数最少的第一个字母([a-zA-Z0-9])。str
  4. 如果可能,我不想使用任何语句(例如:if-then-else)、循环(For/While)或用户定义的函数。使用命令、库函数(如果用户开箱即用)是可以的。

PS:我知道系统级命令确实在幕后调用了所有这些东西,但是如果可能的话,我正在命令行($提示符)中寻找最少的代码。

我尝试了以下看起来很丑的非单线尝试,如下所示,这里我有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

我相信有可能在 BASH中实现我正在寻找的One-liner(即通过使用一堆常见的 Linux 命令和管道| );只是想挑选你的大脑!我知道有比我更好的shell专家。

我在网上找到的大多数解决方案都不会保持顺序(这对我来说很重要),而只是给出一个字符的最高/最低出现/计数。

4

6 回答 6

4

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


编辑:由于 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

说明:为上述添加详细说明。

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 中出现的第一个最小值(顺便说一句,通过此解决方案,所有具有相同最小值的项目也可以打印,在此代码的最后一个打印语句中进行微小更改)。用 GNU 编写和测试awk

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 可以以他想要的任何方式使用,这样做是为了展示它是如何工作的。

于 2020-06-06T10:54:29.950 回答
3

答案 #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

这给了我一个 1400 万字符的文件 ( newgiga.txt)。

我针对 1400 万个字符的文件运行了几个计时测试以及一个新的awk解决方案(见下文),并得出了以下计时:

  • 基于文件/数组的解决方案需要 15 秒awk(请参阅我之前的答案 - 上面)
  • 25 秒 OPsed/grep/echo/uniq/tr/sort回答
  • 使用 RavinderSingh13 的awk解决方案超过 4 分钟(实际在 4 分钟后点击 ^C)
  • 6 秒,使用基于新文件/substr()awk解决方案(见下文)

注意:对于针对我的特定newgiga.txt文件运行的所有解决方案,最终答案是字母Z(出现 365 次)。

split/array通过用一系列调用替换代码substr(),并对all数组的索引方式进行小幅更改,我能够将之前基于文件/数组awk解决方案的运行时间缩短约 60%:

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()调用。

于 2020-06-06T12:13:54.717 回答
1

答案 #4 - 文件/substr()/reduced-array-usage 解决方案

在与@AKS 反复讨论并使用更大的数据集(使用 36 MB 文件的最新测试)后,awk/array内存问题突然出现(例如,对于更大的数据集,各种awk答案 - 到目前为止- 需要 6-8 GB 的 RAM)。

我解决内存问题的第一次尝试是将所有输入复制到一个新变量中;是的,这意味着将 36 MB 的数据复制到一个awk变量中,但这仍然远远小于 6-8 GB 的 RAM。

使用@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 MB 的内存(比之前答案的 6-8 GB 好得多),同时运行速度也与以前大致相同。


尝试了一种消除copy变量的解决方案,而是再次处理输入文件。结果:

  • 总内存使用量下降了约 30 MB(至约 130 MB)
  • 总运行时间增加了约 2 秒

因此,权衡取舍并不值得付出努力。

于 2020-06-06T22:42:51.600 回答
0

尝试

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

于 2020-06-06T12:00:06.307 回答
0

好吧,我想我终于明白了(从早上 5 点开始吃了 3 个胡萝卜布丁碗);我有动力了!!由你们。

  • 没有 for使用循环或if-then条件。
  • 操作期间不创建变量。
  • 在以下解决方案之前使用time- 显示它在1.5秒内完成的最大文件上完成real 0m1.428s;而awk使用文件的解决方案大约需要4.5秒)。
  • 看起来更像是单线(使用justLinux 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)

如果想查看计数(有点超出范围),他们可以在上面的 cut 命令中更改-f2-f1

这是脚本:https ://repl.it/@asangal/find1stleastoccurrencecharmaintainorderanyleastsize

于 2020-06-06T13:44:59.350 回答
0

如果文件适合内存:

<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}}'
于 2020-06-08T03:51:57.590 回答