我希望一些Perl大师可以对以下内容发表意见.这是我能找到的最小可能的例子,它可以重现我的问题:
>./perl -e 'print (("a".("f"x32767)."a") =~ /a(?:[^a]|bb)*a/)'
1
Run Code Online (Sandbox Code Playgroud)
但
>./perl -e 'print (("a".("f"x32768)."a") =~ /a(?:[^a]|bb)*a/)'
>
Run Code Online (Sandbox Code Playgroud)
我从源代码编译了最新的Perl,看它是否能解决问题:
>./perl -v
This is perl 5, version 20, subversion 1 (v5.20.1) built for i686-linux
Run Code Online (Sandbox Code Playgroud)
这是一个错误(看起来像我)?
作为一个常见的例子,假设我们想要匹配一些单词模式,$word_pattern但它周围可能有空格.这是正则表达式的常见用法.通常人们会写
/\s*$word_pattern\s*/
Run Code Online (Sandbox Code Playgroud)
但是在失败的情况下效率低下不是吗?效率代码不应该是:
/(?>\s*)$word_pattern\s*/
Run Code Online (Sandbox Code Playgroud)
但我从来没有看到实际写的......
另外:是的我现在做了基准测试,并且由于其中一个响应者可能在这里有空白问题,我不想使用它.
所以现在我有一个非常长的文件a.txt(1GB)完全填充字符a.
然后
perl -ne 'print !/a*b/' < a.txt
perl -ne 'print !/(?>a*)b/' < a.txt
Run Code Online (Sandbox Code Playgroud)
两者都占用了很多,但相同的时间(超过了读取文件本身所需的时间).
我根本不明白.谁能解释一下怎么会这样?Perl文档清楚地说,在第一种情况下,会有回溯.
> cat warning.cpp
#pragma foobar
> cat no_warning.cpp
#pragma message "foobar"
> g++ -Wall -Wno-foobar -c warning.cpp
warning.cpp:1:0: warning: ignoring #pragma foobar [-Wunknown-pragmas]
cc1plus: warning: unrecognized command line option "-Wno-foobar" [enabled by default]
> g++ -Wall -Wno-foobar -c no_warning.cpp
no_warning.cpp:1:17: note: #pragma message: foobar
Run Code Online (Sandbox Code Playgroud) 我使用这个LD_PRELOAD技巧来捕获open64()调用,我想我知道如何正确地执行它:使用foobar编译的程序
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main() {
open64("foobar.txt", 0);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我抓住open64了我的期望:
>LD_PRELOAD=$PWD/catch.so ./foobar
open64 called
Run Code Online (Sandbox Code Playgroud)
但是,当open64替换为fopen64:
#include <stdio.h>
int main() {
fopen64("foobar.txt", "r");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在open64没有被抓住.为什么?
如果fopen64打电话open,我确实有两个open并且open64截获,没有人被抓住.
程序的两个版本foobar,当执行时strace,显示open被调用,这意味着fopen64内部调用open或open64.
我认为也许某些东西是静态链接的,但事实并非如此:
>ldd foobar
Run Code Online (Sandbox Code Playgroud)
节目
libc.so.6 => /lib64/libc.so.6
Run Code Online (Sandbox Code Playgroud)
这是一个共享库,和
>nm /lib64/libc.so.6
Run Code Online (Sandbox Code Playgroud)
显示两者open64 …
我有一个破折号外壳安装为/bin/dash. 我查了dash的手册,和POSIX shell的手册是一样的,没有说shell的版本。
破折号 --version
不起作用。
如何告诉我有破折号的版本号?
补充:有些人指着我使用 Ubuntu 命令,好吧,不,我不是在运行 Ubuntu,我在运行 Centos。
每个幼儿园的孩子都知道,Linux 中的文件路径不能超过PATH_MAX字符。
但是在我的系统上试验,命令
ln -s $(for i in {0..1024}; do printf dir/../; done)foobar foobar1
Run Code Online (Sandbox Code Playgroud)
失败并显示错误消息File name too long。
我不太明白为什么。这里没有长文件名,只有文件的预期内容foobar1很长。甚至还没有人试图遍历符号链接的内容以到达目标。当然,我可以拥有一个内容远大于PATH_MAX.
另一方面,像这样的命令
for i in {0..4096}; do ln -s $i $(expr $i + 1); done
Run Code Online (Sandbox Code Playgroud)
成功。只有当我试图遍历链时,系统才会抱怨。
但我对遍历任何东西都不感兴趣。我正在编写必须读取符号链接值(无需遍历)的软件,我想知道是否需要考虑很长的值。
在 Linux 中哪里记录了这是不允许的?或者它是否依赖于文件系统实现并且可以更改?
当我尝试编译此 SSCCE 代码时(在 Ubuntu 16.04 ,内核 4.15 上)
\n// defines and include needed according to openat manpage at man7.org\n#define _POSIX_C_SOURCE 200809L\n#define _ATFILE_SOURCE\n#include <sys/types.h> // additional include according to die.net , but not man7.org\n#include <sys/stat.h> // additional include according to die.net , but not man7.org\n#include <fcntl.h> \n\nint main() {\n openat(3, "foobar", O_NOATIME, 0);\n}\nRun Code Online (Sandbox Code Playgroud)\n我明白了
\nerror: \xe2\x80\x98O_NOATIME\xe2\x80\x99 undeclared \nRun Code Online (Sandbox Code Playgroud)\n我并不是真的在寻找有人告诉我:“它在文件中<xxx.h>,包括它”。我可以找到它在我的系统上的位置。
我正在编写的代码不仅要在这个系统上编译并且我很高兴,而且还会被其他人或其他系统编译。我必须根据一些信誉良好的来源(例如 man7 或 die.net,但他们的文档对我不起作用)中记录的内容来编写所有代码。这样做的原因是“合理的否认”——如果它们无法编译,我不能只是说“它对我有用”——那是蹩脚的;我需要能够说“它在某某神圣的来源中说它应该有效”并且“我检查过”。
\n使用LD_PRELOAD我正在打印所有打开的文件描述符,但...at系统调用使用不同的文件描述符.为什么?
最简单的例子:
这是我的库foobar.c- 它拦截所有open...调用并打印文件描述符,并打印调用参数unlinkat
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>
int open(const char *pathname, int flags, ...)
{
int fd = ((int (*) (const char*, int, ...))dlsym(RTLD_NEXT, "open"))(pathname, flags);
printf("open pathname %s fd %d\n", pathname, fd);
return fd;
}
int open64(const char *pathname, int flags, ...)
{
int fd = ((int (*) (const char*, int, ...))dlsym(RTLD_NEXT, "open64"))(pathname, flags);
printf("open64 pathname %s fd %d\n", …Run Code Online (Sandbox Code Playgroud) 我在一些Linux bash脚本中看到,例如configure由这样的autoconf序列生成的脚本
exec 5>>config.log
Run Code Online (Sandbox Code Playgroud)
(......)
echo foo >&5
Run Code Online (Sandbox Code Playgroud)
(......)
echo bar >&5
Run Code Online (Sandbox Code Playgroud)
(重复多次)
在我看来,人们可以做到
echo foo >>config.log
Run Code Online (Sandbox Code Playgroud)
这更简单.这样做有什么意义呢exec.必须有一些我不理解的理由.它是什么?
我可以在Python中使用"静态"变量的匿名函数吗?
例如
lambda x: re.compile(r'foobar').match(x)
Run Code Online (Sandbox Code Playgroud)
是不是很好,因为它可能会在每次调用时重新编译(如果re用完了缓存 - 感谢响应者指出缓存机制).
我可以这样做而无需重新编译:
def f(line):
try:
f.c
except:
f.c = re.compile(r'foobar')
return f.c.match(line)
Run Code Online (Sandbox Code Playgroud)
怎么用lambda做,不重新编译?
好吧,我不想使用辅助函数,在lambda中使用.使用lambdas的全部意义是"匿名".所以是的,lambda是匿名的,并且是独立的.
linux ×5
c ×2
perl ×2
regex ×2
autoconf ×1
bash ×1
c++ ×1
centos ×1
dash-shell ×1
filesystems ×1
g++ ×1
lambda ×1
ld-preload ×1
linux-kernel ×1
optimization ×1
python ×1