Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 寻求了解一种模式的参考_[0美元]和#x2B+&引用;_Regex_Sorting_Awk - Fatal编程技术网

Regex 寻求了解一种模式的参考_[0美元]和#x2B+&引用;

Regex 寻求了解一种模式的参考_[0美元]和#x2B+&引用;,regex,sorting,awk,Regex,Sorting,Awk,我是一个AWK新手,使用GNU实用程序移植到Windows(UNXUtils)和gawk而不是AWK。这个论坛上的一个解决方案就像绝对魔法一样,我正试图找到一个我可以阅读的源代码,以便更好地理解该解决方案中提供的模式表达式 在Dimitre Radoulov的回答中,他提供了以下代码 zsh-4.3.9[t]% awk '!_[$0]++' file 作为一种解决方案,用于选择具有重复和混乱元素的列表中的元素,每个元素只列出一次 我以前使用过sort | uniq来实现这一点,这对于小型测

我是一个AWK新手,使用GNU实用程序移植到Windows(UNXUtils)和gawk而不是AWK。这个论坛上的一个解决方案就像绝对魔法一样,我正试图找到一个我可以阅读的源代码,以便更好地理解该解决方案中提供的模式表达式

在Dimitre Radoulov的回答中,他提供了以下代码

zsh-4.3.9[t]%   awk '!_[$0]++' file
作为一种解决方案,用于选择具有重复和混乱元素的列表中的元素,每个元素只列出一次

我以前使用过
sort | uniq
来实现这一点,这对于小型测试文件来说非常有效。对于我的实际问题(2006年4月,从印度国家证券交易所16天的归档订单研究数据中提取公司符号列表,多个文件中有1.29亿多条记录),排序负担变得太重了。uniq只消除相邻的重复项

为了我的Win GNU gawk复制上面的行,我使用

C:\Users\PAPERS\>  cat ..\Full*_Symbols.txt | gawk "!_[$0]++"  | wc -l

946
这表明1.29亿多条记录涉及946家不同的公司,这是一个非常合理的答案。我花了不到5分钟的时间在我那台普通的Windows机器上,几个小时的分类工作让我筋疲力尽

查看了我在网上搜索过的所有awk文本,虽然对部分模式的解释很清楚(
不起作用,
$0
是当前的全部记录),但对于下划线
我找不到任何解释,并且只在示例中看到了
++
“将计数器更新1。”


如果您有任何合适的文本或网络参考资料来充分理解此示例,我将不胜感激,因为我认为它在其他相关案例中也会对我有所帮助。谢谢。最好的,

它真的非常聪明

它创建一个关联数组(意味着“索引”可以是任何东西,而不仅仅是一个数字)。如果元素不存在(为零),则创建它(通过增加它),并且当存在匹配时,
awk
执行默认操作(即打印输入行)。一旦找到值,
\uU0]
将为非零,因此如果再次遇到相同的值,则表达式将为false,并且不会打印任何内容

我认为下划线只是一个“普通”变量名(数组需要一个名称,下划线与
monkey
一样有效,但更为“匿名”)。
经典!

另一方面,此命令可以扩展为:

awk '{if (array[$0]==0) {array[$0]+=1;print}}' 
您可以理解为:

_ represents associative array named "array"

!_[$0]  represents (array[$0]==0)

_[$0]++  represents array[$0]+=1

除了一些人认为使用下划线字符作为变量名(在本例中为数组)来混淆代码是聪明的做法外,
\uuuu
没有任何解释。就像在C中一样,awk中的变量名可以以任何字母或下划线开头,但显然目的并不是让它们只是下划线-这就是ju真可笑

编写代码的更常见、更合理的方法是命名数组
seen
或类似名称,以便您了解它的用途:

awk '!seen[$0]++'

上面介绍了一个名为
seen
的数组,该数组由当前行上的文本索引。第一次测试时,每个索引处的数组都有零值,再次使用同一字符串测试时,由于后增量,该数组的值为1,依此类推。因此,只有在看到给定字符串的第一次出现时,该值的反比才为真在我第一次理解数组的这个用法之前,我确实花了一个小时。所以,为了帮助我自己,前一段时间我检查了发生了什么

所以我对它进行了分类,并使用一些测试对它进行了检查。
\u[$0]
更改为
A[$0]

!一个[$0]+
变成
测试数组
A[$0]
是否不是
真,如果不是真,则打印该行,因为它没有默认操作,
awk
的默认操作是打印该行。
测试后,它会将
1
添加到数组中,因为
A[$0]+
=
A[$0]=A[$0]+1
。当
+
位于数组后面时,增量在测试后完成

因此,
!一个[$0]+
可以更改为:

{if (!A[$0]++) print $0}
还有一些额外的信息文本

{if (!A[$0]++) print "output="$0; else print "output="}
将此数据作为输入

cat file
one
two
three
four
two
five
three
six
我得到这个输出:

awk '{printf "line=%s array=%s ",$0,A[$0]} {if (!A[$0]++) print "output="$0; else print "output="}'
line=one array= output=one
line=two array= output=two
line=three array= output=three
line=four array= output=four
line=two array=1 output=
line=five array= output=five
line=three array=1 output=
line=six array= output=six
有信息

awk '{printf "line=%s array=%s ",$0,A[$0]} {if (!A[$0]++) print "output="$0; else print "output="}'
line=one array= output=one          # line is `one` and since its not found before array is blank (same as 0) and not true, print the line
line=two array= output=two          # line is `two` and since its not found before array is blank (same as 0) and not true, print the line
line=three array= output=three      # line is `threw` and since its not found before array is blank (same as 0) and not true, print the line
line=four array= output=four        # line is `four` and since its not found before array is blank (same as 0) and not true, print the line
line=two array=1 output=            # line is `two` and its found before giving array 1 and true, do not print the line
line=five array= output=five        # line is `five` and since its not found before array is blank (same as 0) and not true, print the line
line=three array=1 output=          # line is `three` and its found before giving array 1 and true, do not print the line
line=six array= output=six          # line is `six` and since its not found before array is blank (same as 0) and not true, print the line
因此,将不会打印第二行的
2
3

在数据上使用原始表达式仅给出唯一值:

awk '!_[$0]++' file
one
two
three
four
five
six
要获取所有副本,请执行以下操作:

awk '_[$0]++'
two
three

+1为我的解释提供非常清晰的替代方案-但要挑剔的是,
打印将在增量操作之后进行,而不是之前…您不需要
排序| uniq
,因为
排序-u
工作正常。@edmorton-这比
排序| uniq
快吗?我想是这样,但您曾经对它进行过基准测试吗?从未测试过将其标记为我从未使用过
sort | uniq
,也从未使用过速度不够快的
sort-u
脚本。另一点需要注意的是,关联数组非常神奇。奇妙的神奇。现在很多语言都有它们,而且它们的价格往往惊人地便宜。@DonalFellows I ag它们是一颗宝石,访问速度比你想象的要快得多;几乎与数组大小无关。@DonalFellows和其他评论者:衷心感谢。这非常有帮助。+1:)我喜欢uu作为一个标识符,但对我来说,它更通用、临时、匿名……默认,就像Perl的一样。对我来说,一行程序和简短的一次性脚本都可以。软件工程中没有任何原则表明匿名标识符是可取的。当函数、变量等c、 有意义的名称,而不是像
\uu
这样的名称。即使是一个单字母变量名称也比
\u
好得多,因为至少这不像
[
)这样的语言结构。