Oct
31
在shell里头,有些程序(比如ssh)的交互是从pty中读取的数据,直接的重定向无法解决,因此需要用到expect这种东西。不过这货的编译比较麻烦,各种依赖。幸好有个pexpect是纯python的,存档留个记录。
如果密码错误的话,输出
如果正确,则输出
#!/usr/bin/python
import sys
import pexpect
password = 'password'
expect_list = ['(yes/no)', 'password:']
p = pexpect.spawn('ssh username@localhost ls')
try:
while True:
idx = p.expect(expect_list)
print p.before + expect_list[idx],
if idx == 0:
print "yes"
p.sendline('yes')
elif idx == 1:
print password
p.sendline(password)
except pexpect.TIMEOUT:
print >>sys.stderr, 'timeout'
except pexpect.EOF:
print p.before
import sys
import pexpect
password = 'password'
expect_list = ['(yes/no)', 'password:']
p = pexpect.spawn('ssh username@localhost ls')
try:
while True:
idx = p.expect(expect_list)
print p.before + expect_list[idx],
if idx == 0:
print "yes"
p.sendline('yes')
elif idx == 1:
print password
p.sendline(password)
except pexpect.TIMEOUT:
print >>sys.stderr, 'timeout'
except pexpect.EOF:
print p.before
如果密码错误的话,输出
引用
The authenticity of host 'localhost (127.0.0.1)' can't be established.
RSA key fingerprint is fe:00:00::00:00:00:00:00:00:00:00:00:00:00:00.
Are you sure you want to continue connecting ((yes/no) yes
)? yes
Warning: Permanently added 'localhost' (RSA) to the list of known hosts.
username@localhost's password: password
Permission denied, please try again.
username@localhost's password: password
Permission denied, please try again.
username@localhost's password: password
Permission denied (publickey,gssapi-with-mic,password).
RSA key fingerprint is fe:00:00::00:00:00:00:00:00:00:00:00:00:00:00.
Are you sure you want to continue connecting ((yes/no) yes
)? yes
Warning: Permanently added 'localhost' (RSA) to the list of known hosts.
username@localhost's password: password
Permission denied, please try again.
username@localhost's password: password
Permission denied, please try again.
username@localhost's password: password
Permission denied (publickey,gssapi-with-mic,password).
如果正确,则输出
引用
username@localhost's password: password
a
b
bin
code
a
b
bin
code
Oct
30
比赛的起因是这样的,@Tranch同学在SegmentFault.com提了个问题,求一个代码,可以列出字符串"qwerty"被 "." 分割的所有情况,比如 q.werty qwe.rty q.w.e.r.t.y 等等。
这个问题其实很简单,qwerty中间最多可以塞5个". ",每个地方用1表示塞,0表示不塞,也就是正好循环 2^5 次就行了(对于全0的情况不做特别要求,可有可无),实现起来也非常容易,这里是写这篇文章时补充的一个C语言实现:
不过当时没想写这样的代码,而是特意脑抽用python写了个递归的版本:
因为前一段时间看到 这里用21行python代码实现了一个拼写检查器,于是一时兴起,简化成了这个等价但是更难读的版本:
虽然已经很短了,但是我还是想知道,是否有更简单些的实现(一定程度上可以忽略效率和可读性),于是在MSTC的群里发了这个问题,简单起见,把字符串改成了"abcde",问问有没有更短的代码来给出各种组合。
然后 @杭神 扔了个代码出来,被喷“能不能用人话”。这段代码看起来是有些费解,主要思路是,生成 ['****', '***.', '**..', '*...', '....'] 的各种排列,然后用zip('abcd', p)交错组合起来(再删掉'*'):
然后 @霄妹纸 说,实际上那个是笛卡尔积。于是用上itertools.product,再改善下语法,可以写成这样,看起来就清晰多了:
@霄妹纸 还给出了另外两个奇葩的代码,一个是 C 的,充分利用和宏、main函数的参数和递归:
另一个是ruby的:
由于不懂ruby语法,所以这个代码我也只能勉强看看,不过思路上跟上面的python代码是一样的,使用笛卡尔积生成组合序列,然后再与'abcde'交错组合。
结果是,ruby赢了(58个字节),python紧随其后(80字节,不包括import),C语言则意外地以106个字节的代码实现了这个目标。
这个问题从实践的角度上来说没有太大意义,不过可以对比下,不同的语言(C/Ruby/Python)、不同的编程范型(过程式/函数式)的表达方式,一窥函数式编程的魅力~
这个问题其实很简单,qwerty中间最多可以塞5个". ",每个地方用1表示塞,0表示不塞,也就是正好循环 2^5 次就行了(对于全0的情况不做特别要求,可有可无),实现起来也非常容易,这里是写这篇文章时补充的一个C语言实现:
#include <stdio.h>
int main()
{
char str[] = "qwerty";
int i, j;
for (i = 0; i < (1<<5); i++)
{
for (j = 0; j < 5; j++)
{
putchar(str[j]);
if (((i >> j) & 1) == 1)
putchar('.');
}
printf("y\n");
}
return 0;
}
int main()
{
char str[] = "qwerty";
int i, j;
for (i = 0; i < (1<<5); i++)
{
for (j = 0; j < 5; j++)
{
putchar(str[j]);
if (((i >> j) & 1) == 1)
putchar('.');
}
printf("y\n");
}
return 0;
}
不过当时没想写这样的代码,而是特意脑抽用python写了个递归的版本:
def add_dots_l(str):
ret = []
for i in range(1, len(str)):
left = str[:i]
right = str[i:]
ret.append(left + '.' + right)
ret += [j + '.' + right for j in add_dots_l(left)]
ret += [left + '.' + j for j in add_dots_l(right)]
return set(ret)
ret = []
for i in range(1, len(str)):
left = str[:i]
right = str[i:]
ret.append(left + '.' + right)
ret += [j + '.' + right for j in add_dots_l(left)]
ret += [left + '.' + j for j in add_dots_l(right)]
return set(ret)
因为前一段时间看到 这里用21行python代码实现了一个拼写检查器,于是一时兴起,简化成了这个等价但是更难读的版本:
def add_dots(s):
r = [s[:i] + '.' + s[i:] for i in range(1, len(s))]
r += [j + '.' + s[i:] for i in range(1, len(s)) for j in add_dots(s[:i])]
r += [s[:i] + '.' + j for i in range(1, len(s)) for j in add_dots(s[i:])]
return set(r)
r = [s[:i] + '.' + s[i:] for i in range(1, len(s))]
r += [j + '.' + s[i:] for i in range(1, len(s)) for j in add_dots(s[:i])]
r += [s[:i] + '.' + j for i in range(1, len(s)) for j in add_dots(s[i:])]
return set(r)
虽然已经很短了,但是我还是想知道,是否有更简单些的实现(一定程度上可以忽略效率和可读性),于是在MSTC的群里发了这个问题,简单起见,把字符串改成了"abcde",问问有没有更短的代码来给出各种组合。
然后 @杭神 扔了个代码出来,被喷“能不能用人话”。这段代码看起来是有些费解,主要思路是,生成 ['****', '***.', '**..', '*...', '....'] 的各种排列,然后用zip('abcd', p)交错组合起来(再删掉'*'):
from itertools import permutations as p #itertools.permutations是python2.6引入的
map(lambda p: ''.join(j for i in zip('abcd', p) for j in i).replace('*', '') + 'e', [''.join(y) for x in map(lambda i: set(p('*' * (4-i) + '.' * i)), range(5)) for y in x])
map(lambda p: ''.join(j for i in zip('abcd', p) for j in i).replace('*', '') + 'e', [''.join(y) for x in map(lambda i: set(p('*' * (4-i) + '.' * i)), range(5)) for y in x])
然后 @霄妹纸 说,实际上那个是笛卡尔积。于是用上itertools.product,再改善下语法,可以写成这样,看起来就清晰多了:
from itertools import product #itertools.product也是2.6引入的
map(lambda p: ''.join(i + j for i, j in zip('abcd', p)) + 'e', product(['.', ''], repeat = 4))
map(lambda p: ''.join(i + j for i, j in zip('abcd', p)) + 'e', product(['.', ''], repeat = 4))
@霄妹纸 还给出了另外两个奇葩的代码,一个是 C 的,充分利用和宏、main函数的参数和递归:
#define z(a,b) printf(#a"%s",(x>>b)&1?".":""),
main(x){z(a,3)z(b,2)z(c,1)z(d,0)puts("e");16-x&&main(x+1);}
main(x){z(a,3)z(b,2)z(c,1)z(d,0)puts("e");16-x&&main(x+1);}
另一个是ruby的:
p ("b".."e").inject(["a"]){|a,q|a.product [q,"."+q]}.map &:join
如果是ruby 1.9+的话,还可以再少几个字符:p (?b..?e).inject([?a]){|a,q|a.product [q,?.+q]}.map&:join
由于不懂ruby语法,所以这个代码我也只能勉强看看,不过思路上跟上面的python代码是一样的,使用笛卡尔积生成组合序列,然后再与'abcde'交错组合。
结果是,ruby赢了(58个字节),python紧随其后(80字节,不包括import),C语言则意外地以106个字节的代码实现了这个目标。
这个问题从实践的角度上来说没有太大意义,不过可以对比下,不同的语言(C/Ruby/Python)、不同的编程范型(过程式/函数式)的表达方式,一窥函数式编程的魅力~
Oct
23
用Google的第一大烦恼是随时被墙。
番羽土啬吧。
用Google的第二大烦恼是,点击的链接总要过一道Google的统计。比如搜索test,第一条是www.test.com,但是点击的时候,打开的页面是
http://www.google.com.hk/url?sa=t&rct=j&q=&esrc=s&frm=1&source=web&cd=1&ved=0CCoQFjAA&url=http%3A%2F%2Fwww.test.com%2F&ei=LHuGUMSUDKf-iAeg7YCAAg&usg=AFQjCNH21KLjC0CBkjon2DwD_CZ0HApLMw
经常发生的事情是,一直卡在这个链接上,不管是否番羽土啬,反正总是跳不过去;而大部分情况下,目标网页不需要番羽土啬也是可以顺利打开的。
至于Google呢,他才不管你是不是总卡死在这个链接,反正他们要的是你这次点击的数据。
这个问题,可以借助一个叫"Don't Track Me Google"的grease monkey脚本来实现:
http://userscripts.org/scripts/show/121923
对于Firefox,需要安装Grease Monkey插件,而Chrome用户则方便了,直接可以作为插件使用。
页面右上方有个不起眼的 Install 按钮,点一下,会下载一个 xxxx.user.js ,旧版本的chrome就直接当插件安装上去了,新版本的会提示你,不能这么安装非官方来源的插件。解决方法是:打开扩展管理页面,把这个 js 文件拖进去,会问你是否要安装,点击“添加”,done。
番羽土啬吧。
用Google的第二大烦恼是,点击的链接总要过一道Google的统计。比如搜索test,第一条是www.test.com,但是点击的时候,打开的页面是
http://www.google.com.hk/url?sa=t&rct=j&q=&esrc=s&frm=1&source=web&cd=1&ved=0CCoQFjAA&url=http%3A%2F%2Fwww.test.com%2F&ei=LHuGUMSUDKf-iAeg7YCAAg&usg=AFQjCNH21KLjC0CBkjon2DwD_CZ0HApLMw
经常发生的事情是,一直卡在这个链接上,不管是否番羽土啬,反正总是跳不过去;而大部分情况下,目标网页不需要番羽土啬也是可以顺利打开的。
至于Google呢,他才不管你是不是总卡死在这个链接,反正他们要的是你这次点击的数据。
这个问题,可以借助一个叫"Don't Track Me Google"的grease monkey脚本来实现:
http://userscripts.org/scripts/show/121923
对于Firefox,需要安装Grease Monkey插件,而Chrome用户则方便了,直接可以作为插件使用。
页面右上方有个不起眼的 Install 按钮,点一下,会下载一个 xxxx.user.js ,旧版本的chrome就直接当插件安装上去了,新版本的会提示你,不能这么安装非官方来源的插件。解决方法是:打开扩展管理页面,把这个 js 文件拖进去,会问你是否要安装,点击“添加”,done。
Oct
19
经常是用vim打开了某个/etc下的文件,使用 :w 保存的时候提示 "E45: 'readonly' option is set (add ! to override)",而 :w! 则提示 "E212: Can't open file for writing"。通常的解决方案是 :q! 然后 sudo !! 再次编辑,然后保存。
虽然挺麻烦,但是一直也就将就用了。今天有人在SegmentFault.com提出了这个问题,于是仔细考虑了下,的确还是有办法实现的:
:%!sudo bash -c "cat > '%'" #为了防止文件名中的空格之类特殊字符,最好在后一个%前后加上引号
:w !sudo tee % #另一个回答给出的这个方法更简洁,出自 http://vim.wikia.com/wiki/Su-write
其实最初的想法是 :%!sudo cat > % ,但是由于权限的问题(vim打开的shell没法清空当前文件),所以还是得请shell进来掺和一脚:先用sudo给shell提权,然后shell再执行cat将stdin的内容输出到%。
p.s. 顺便给不了解 :%! 这个含义的同学普及一下, :!xxx 是执行 xxx 命令, :%!xxx 则是把当前缓冲区的所有内容当成 stdin 去执行 xxx 命令,然后将xxx的stdout再替换当前缓冲区的内容。比较常见的用法是 :%!sort 给文件所有的行排序,然后 :%!uniq 去重。另外%可以用范围来代替(同 :s 命令的范围)。
虽然挺麻烦,但是一直也就将就用了。今天有人在SegmentFault.com提出了这个问题,于是仔细考虑了下,的确还是有办法实现的:
引用
:w !sudo tee % #另一个回答给出的这个方法更简洁,出自 http://vim.wikia.com/wiki/Su-write
其实最初的想法是 :%!sudo cat > % ,但是由于权限的问题(vim打开的shell没法清空当前文件),所以还是得请shell进来掺和一脚:先用sudo给shell提权,然后shell再执行cat将stdin的内容输出到%。
p.s. 顺便给不了解 :%! 这个含义的同学普及一下, :!xxx 是执行 xxx 命令, :%!xxx 则是把当前缓冲区的所有内容当成 stdin 去执行 xxx 命令,然后将xxx的stdout再替换当前缓冲区的内容。比较常见的用法是 :%!sort 给文件所有的行排序,然后 :%!uniq 去重。另外%可以用范围来代替(同 :s 命令的范围)。