数组和列表之间以及列表和标量上下文之间的区别已经在去年的Perl社区中进行了相当多的讨论(并且每年都是如此).我已阅读过chromatic和friedo的文章,以及这个推荐的修士节点.现在我想了解goatse运营商,中记录perlsecret.
这是我用来研究它的一些代码:
# right side gets scalar context, so commas return rightmost item
$string = qw(stuff junk things);
say $string; # things
# right side gets list context, so middle is list assigned in scalar context
$string = () = qw(stuff junk things);
say $string; # 3
# right side gets list context, so creates a list, assigns an item to $string2, and
# evaluates list in scalar context to assign to …Run Code Online (Sandbox Code Playgroud) 在回答这个关于与空间(和潜在的其他字符)的文件名的安全逃逸的问题,其中一个答案说使用Perl的内置quotemeta功能.
quotemeta的文档说明:
quotemeta (and \Q ... \E ) are useful when interpolating strings
into regular expressions, because by default an interpolated variable
will be considered a mini-regular expression.
Run Code Online (Sandbox Code Playgroud)
在quotemeta的文档,其使用的唯一一提的是逃避所有以外的字符/[A-Za-z_0-9]/用\在正则表达式中使用.它没有说明文件名的用途.然而,这似乎是一种非常令人愉快的,如果没有记录的副作用.
在对SinanÜnür 回答早期问题的评论中,霍布斯说:
壳逸出是从正则表达式逃逸不同,虽然我不能想出的情况下quotemeta会给一个真正不安全的结果,它并不意味着任务.如果你必须逃避,而不是绕过shell,我建议尝试String :: ShellQuote采用更加保守的方法,使用sh单引号来除去单引号本身和单引号的反斜杠之外的所有内容. - 霍布斯于2009年8月13日14:25
是否安全 - 完全 - 使用quotemeta代替像String :: Shellquote这样更保守的文件引用?quotemeta utf8或多字节字符安全吗?
我把一个不明确的测试放在一起.除了带有a \n或其中的文件名或目录名之外,quotemeta似乎运行良好\r.虽然很少见,但这些字符在Unix中是合法的,我已经看过了.回想一下,LF,CR和NUL等某些字符无法转义\.我用带有quotemeta的700k文件读取了我的硬盘,没有出现任何故障.
我怀疑(虽然我还没有证明),quotemeta可能会因多字节字符而失败,其中一个或多个字节属于ASCII范围.例如,à可以编码为一个字符(UTF8 C3 A0)或两个字符(U + 0061表示a u + 0300是组合格雷夫口音).我在quotemeta中遇到的唯一失败是文件带有\n或者\r …
假设我有一个简单的Python列表,如下所示:
>>> l=['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
Run Code Online (Sandbox Code Playgroud)
现在假设我想要组合l[2:6]成这样的单个元素:
>>> l
['0', '1', '2345', '6', '7', '8', '9']
Run Code Online (Sandbox Code Playgroud)
我能够分步进入一个新列表,如下所示:
>>> l2=l[0:2]
>>> l2.append(''.join(l[2:6]))
>>> l2.extend(l[6:])
>>> l2
['0', '1', '2345', '6', '7', '8', '9']
Run Code Online (Sandbox Code Playgroud)
有没有办法(我错过了)在原始列表上更简单地执行此操作l?
编辑
像往常一样,Sven Marnach有一个完美的即时答案:
l[2:6] = ["".join(l[2:6])]
Run Code Online (Sandbox Code Playgroud)
我试过了:
l[2:6] = "".join(l[2:6])
Run Code Online (Sandbox Code Playgroud)
但是没有大括号,连接产生的字符串被视为可迭代,将每个字符放回列表并反转连接!
考虑:
>>> l=['abc','def','ghk','lmn','opq']
>>> l[1:3]=[''.join(l[1:3])]
>>> l
['abc', 'defghk', 'lmn', 'opq'] #correct
>>> l=['abc','def','ghk','lmn','opq']
>>> l[1:3]=''.join(l[1:3])
>>> l
['abc', 'd', 'e', 'f', 'g', 'h', …Run Code Online (Sandbox Code Playgroud) 考虑排序字符串的所有后缀的问题,其中后缀是从某个索引i到字符串末尾的子字符串.我们可以创建与已排序后缀的起点相对应的索引列表,而不是创建已排序后缀的列表.然后我们可以这样做:
text = ... some text string ...
sortedIndices = sorted([i for i in range(len(text))],
key = lambda i: text[i:])
Run Code Online (Sandbox Code Playgroud)
这适用于短字符串,但如果字符串足够长,我们将耗尽内存,因为键函数会产生后缀的副本,并且所有键都在一开始就生成.在python 2.7中,有一个灵活的方法,即buffer()函数:
sortedIndices = sorted([i for i in range(len(text))],
key = lambda i: buffer(text, i))
Run Code Online (Sandbox Code Playgroud)
在这种情况下,键只是指向文本字符串的指针,因此所需的总内存要少得多(O(n)vs O(n*n)).因此,它将使用更长的字符串.这在2.7中工作得很漂亮,但是在3.x中,buffer()函数已经被删除而支持memoryview,这与缓冲区不同--AFAIK--支持基于指针的字符串比较(即,不使用tobytes方法,它创建了一个字符串的副本).我的问题是:有没有办法在python 3.x中做类似的事情?
鉴于:
>>> a,b=2,3
>>> c,d=3,2
>>> def f(x,y): print(x,y)
Run Code Online (Sandbox Code Playgroud)
我有一个存在(如无法改变)2位置参数函数,我希望位置参数始终按升序排列; 即,f(2,3)无论我使用哪两个参数(与示例中f(a,b)的相同f(c,d))
我知道我能做到:
>>> f(*sorted([c,d]))
2 3
Run Code Online (Sandbox Code Playgroud)
或者我可以这样做:
>>> f(*((a,b) if a<b else (b,a)))
2 3
Run Code Online (Sandbox Code Playgroud)
(注意这种形式需要元组括号,因为,它的优先级低于三元组...)
要么,
def my_f(a,b):
return f(a,b) if a<b else f(b,a)
Run Code Online (Sandbox Code Playgroud)
所有这些看起来都有些笨拙.我还缺少另一种语法吗?
编辑
我错过了'老派'Python的两个成员元组方法.根据True == 1,False == 0方法索引两个成员元组:
>>> f(*((a,b),(b,a))[a>b])
2 3
Run Code Online (Sandbox Code Playgroud)
也:
>>> f(*{True:(a,b), False:(b,a)}[a<b])
2 3
Run Code Online (Sandbox Code Playgroud)
编辑2
这个愚蠢的练习的原因:numpy.isclose有以下用法说明:
对于有限值,isclose使用以下等式来测试两个浮点值是否相等.
绝对值(a - b)<=(atol + rtol*absolute(b))
上述等式在a和b中不对称,因此在某些罕见的情况下,isclose(a,b)可能与isclose(b,a)不同.
我宁愿没有发生.
我正在寻找最快的方法来确保参数的numpy.isclose顺序是一致的.这就是我回避的原因f(*sorted([c,d]))
我想处理日志文件中的每一行,IP如果行与我的模式匹配,则提取地址。有几种不同类型的消息,在下面的示例中,我正在使用p1 andp2`。
我可以逐行读取文件,并且每一行都与每种模式匹配。但是,由于可以有更多的模式,因此我想尽可能高效地进行操作。我希望将thos模式编译成一个对象,并且只对每行进行一次匹配:
import re
IP = r'(?P<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
p1 = 'Registration from' + IP + '- Wrong password'
p2 = 'Call from' + IP + 'rejected because extension not found'
c = re.compile(r'(?:' + p1 + '|' + p2 + ')')
for line in sys.stdin:
match = re.search(c, line)
if match:
print(match['ip'])
Run Code Online (Sandbox Code Playgroud)
但是上面的代码不起作用,它抱怨ip使用了两次。
实现目标的最优雅方式是什么?
编辑:
我已经根据@Dev Khadka的回答修改了我的代码。
但是我仍然在努力如何正确处理多个ip比赛。下面的代码显示与p1匹配的所有IP:
for line in sys.stdin:
match = c.search(line)
if match:
print(match['ip1'])
Run Code Online (Sandbox Code Playgroud)
但是有些线不匹配p1。他们匹配p2。即,我得到: …
说我有两个清单:
>>> l1=[1,2,3,4]
>>> l2=[11,12,13,14]
Run Code Online (Sandbox Code Playgroud)
我可以将这些列表放在元组或字典中,看起来它们都是返回原始列表的引用:
>>> t=(l1,l2)
>>> d={'l1':l1, 'l2':l2}
>>> id(l1)==id(d['l1'])==id(t[0])
True
>>> l1 is d['l1'] is t[0]
True
Run Code Online (Sandbox Code Playgroud)
由于它们是引用,我可以更改l1元组和字典中的引用数据相应地更改:
>>> l1.append(5)
>>> l1
[1, 2, 3, 4, 5]
>>> t
([1, 2, 3, 4, 5], [11, 12, 13, 14])
>>> d
{'l2': [11, 12, 13, 14], 'l1': [1, 2, 3, 4, 5]}
Run Code Online (Sandbox Code Playgroud)
包括如果我在字典中添加引用d或在元组中附加可变引用t:
>>> d['l1'].append(6)
>>> t[0].append(7)
>>> d
{'l2': [11, 12, 13, 14], 'l1': [1, 2, 3, 4, 5, 6, …Run Code Online (Sandbox Code Playgroud) 我知道我必须遗漏一些简单的东西,但我没有看到它.
如果我有这样的生成器表达式:
>>> serializer=(sn for sn in xrange(0,sys.maxint))
Run Code Online (Sandbox Code Playgroud)
我可以很容易地生成这样的单个整数:
>>> serializer.next()
0
>>> serializer.next()
1
>>> serializer.next()
2
Run Code Online (Sandbox Code Playgroud)
如果我写这样的生成器:
>>> def ser():
... for sn in xrange(0,100000):
... yield sn
Run Code Online (Sandbox Code Playgroud)
这不是bueno:
>>> ser().next()
0
>>> ser().next()
0
>>> ser().next()
0
Run Code Online (Sandbox Code Playgroud)
??? 我错过了什么?
假设我有文件:
$ cat file
This, that;
this-that or this.
Run Code Online (Sandbox Code Playgroud)
(行尾的标点符号并不总是存在......)
现在我想计算单词数(单词被定义为一个或多个 ASCII 不区分大小写的字母。)在典型的 POSIX *nix 中你可以这样做:
sed -nE 's/[^[:alpha:]]+/ /g; s/ $//p' file | tr ' ' "\n" | tr '[:upper:]' '[:lower:]' | sort | uniq -c
1 or
2 that
3 this
Run Code Online (Sandbox Code Playgroud)
使用 grep,您可以缩短一点以仅匹配您定义的单词:
grep -oE '[[:alpha:]]+' file | tr '[:upper:]' '[:lower:]' | sort | uniq -c
# same output
Run Code Online (Sandbox Code Playgroud)
使用 GNU awk,您可以用来FPAT复制仅匹配您想要的内容(忽略排序...):
gawk -v FPAT="[[:alpha:]]+" '
{for (i=1;i<=NF;i++) {seen[tolower($i)]++}}
END {for (e in seen) …Run Code Online (Sandbox Code Playgroud) 我在设置列表时遇到问题,我认为这是因为我初始化错了,这是一种初始化并添加到5000集列表的有效方法吗?
sets = [set()]*5000
i = 0
for each in f:
line = each.split()
if (some statement):
i = line[1]
else:
sets[i].add(line[0])
Run Code Online (Sandbox Code Playgroud)
任何建议将不胜感激