??xml version="1.0" encoding="utf-8" standalone="yes"?>久久久国产精品网站,久久国内免费视频,欧美粉嫩小泬久久久久久久 http://www.shnenglu.com/kenwell/自己学习所?/description>zh-cn Thu, 08 May 2025 16:14:47 GMT Thu, 08 May 2025 16:14:47 GMT 60 工欲善其事必先利其器--打造vim-cscope/ctags工具?转蝲Q?/title> http://www.shnenglu.com/kenwell/archive/2010/08/21/124226.htmlc++ 学习 c++ 学习 Sat, 21 Aug 2010 14:28:00 GMT http://www.shnenglu.com/kenwell/archive/2010/08/21/124226.html http://www.shnenglu.com/kenwell/comments/124226.html http://www.shnenglu.com/kenwell/archive/2010/08/21/124226.html#Feedback 0 http://www.shnenglu.com/kenwell/comments/commentRss/124226.html http://www.shnenglu.com/kenwell/services/trackbacks/124226.html Source Insight的强大的代码分析功能让所有windows下的众生受益菲浅?/p>
而Source insight的h格即使是面对Windows Vista也不逞多。嘿ѝ东西是好东ѝ?/p>
个h认ؓ它也对得赯个h根{可惜没c뀂用不v呀?/p>
咋办呢。用vimQcscope打造一个免费的吧?br>
1安装cscope
cscope的编译和安装没有特别之处Q?/configure - make - make install卛_?br> 安{完毕后先阅读说明: vi /usr/share/vim/vim63/doc/if_cscop.txt.gz |上也有中文版本Qhttp://vcd.gro.clinux.org/doc/if_cscop.html 在vim中用ƈ不需要进行太多的讄Q不q首先vim~译时必d入了cscope的支?br> $ vim --version | grep cscope +cryptv +cscope +dialog_con +diff +digraphs -dnd -ebcdic +emacs_tags +eval 嗯,我用的这个版本的vim是支持cscope的?br>
?照vim里cscope的参考手?在vim中执?:help
cscope"命o)Q把cscope功能加到.vimrc里后(需要你的vim在编译时选择?--enable-cscope"选项Q否则你需要重?
~译vim)Q配|就完成了。然后用下面的命令生成代码的W号索引文gQ?br>
q个命o会生成三个文Ӟcscope.out, cscope.in.out, cscope.po.out?br> 其中cscope.out是基本的W号索引Q后两个文g是?-q"选项生成的,可以加快cscope的烦引速度?br> 上面所用到的命令参敎ͼ含义如下Q?br>
-R : 在生成烦引文件时Q搜索子目录树中的代?br> -b : 只生成烦引文Ӟ不进入cscope的界?br> -k : 在生成烦引文件时Q不搜烦/ usr / include目录 -q : 生成cscope . in . out和cscope . po . out文gQ加快cscope的烦引速度
接下来,可以在vim里读代码了?br> ?
q在使用q程中,发现无法扑ֈC++的类、函数定义、调用关pR仔l阅Mcscope的手册后发现Q原来cscope在生烦引文件时Q只搜烦cd?
C, lex和yacc的文?后缀名ؓ.c, .h, .l,
.y)QC++的文件根本没有生成烦引。不q按照手册上的说明,cscope支持c++和Java语言的文件?br> 于是按照cscope手册上提供的ҎQ先产生一个文件列表,然后让cscope个列表中的每个文仉生成索引?br> Z方便使用Q编写了下面的脚本来更新cscope和ctags的烦引文Ӟ
#!/bin/sh find . -name "*.h" -o -name "*.c" -o -name "*.cc" > cscope.files cscope -bkq -i cscope.files ctags -R
q个脚本Q首先用find命oQ查扑ֽ前目录及子目录中所有后~名ؓ".h", ".c"?.cc"的文Ӟq把查找l果重定向到文gcscope.files中?br> 然后cscopeҎcscope.files中的所有文Ӟ生成W号索引文g?br> 最后一条命令用ctags命oQ生成一个tags文gQ在vim中执?:help tags"命o查询它的用法。它可以和cscope一起用?br> 目前只能在unixpd操作pȝ下用cscopeQ虽然也有windows版本的cscopeQ不q还有很多bug。在Linux技术中坚站上看到有作者在win2000上成功运行了gvim + cscopeQ详情可以参阅: http://www.chinalinuxpub.com/bbs/showthread.php?t=30185 cscope的主在Q?a style="color: #0000ff;" target="_blank">http://cscope.sourceforge.net/ 在vim的网站上Q有很多和cscope相关的插Ӟ可以L一下你有没有所感兴的。搜索结果在q里Q?br> 点这?/u>
Z方便C用cscopeQ我们还需要下载cscope的键盘映设|, q样可以在gvim中简单地通过快捷键来使用 cscopeQ而不必敲复杂的命令了。键盘映可以从 q里下蝲Q?a >http://cscope.sourceforge.net/cscope_maps.vim
下载到?cscope_maps.vim
文g:
cscope_maps.vim.tar.gz
大小:
2KB
下蝲:
下蝲
攑֜gvim的插件目录里Q如 C:\Program Files\Vim\vimfiles\plugin 中。Linux用户可以攑֜ $HOME/.vim/plugin 中?/pre>
↑ 建立W号数据?† 我们假设我们要阅ȝ代码攑֜ D:\src\myproject 下。然后打开命o行,q入源代码所在的目录Q?br>?cscope 建立搜烦文g列表。在命o行中执行以下命oQ?/pre>
dir /s /b *.c *.h > cscope.files 如果你的源代码是C++Q则可以?cpp {扩展名也加入到上面的命令中?/pre>
dir /s /b *.c *.h *cpp *.hpp > cscope.files 如果是Linux用户Q则可以使用 find 命o实现同样的功能:
find $(pwd) -name "*.[ch]" 然后执行以下命oQ?/pre>
cscope -b 执行l束后你可以在当前目录下发现 cscope.out 文gQ这是 cscope 建立的符h据库?/pre>
上面q个命o中,-b参数使得cscope不启动自带的用户界面Q而仅仅徏立符h据库?/pre>
↑ 览源代?† 使用 gvim 打开你的源代码目录中L一个CE序文g。然后在gvim中执行如下命令:
:cscope add D:\src\myproject\cscope.out ׃?gvim 中可以用命令羃写,因此上面的命令可以写成:
:cs a D:\src\myproject\cscope.out q样打开了刚刚徏立的W号数据库。通过下面的命令可以检查数据库q接的存在?/pre>
:cscope show 该命令可以羃写ؓ
:cs s 现在光标移动到源代码中的某个函数名上,依次按下一下组合键Q?/pre>
s E等片刻之后你会在屏q下攄到如下的字样*1Q?/pre>
Cscope tag: display # line filename / context / line 1 342 D:\src\myproject\src\global.h <> void display(void ); 2 616 D:\src\myproject\src\command.c <> display(); 3 138 D:\src\myproject\src\display.c <> display(void ) 4 385 D:\src\myproject\src\main.c <> display(); 5 652 D:\src\myproject\src\main.c <> display(); 6 663 D:\src\myproject\src\main.c <> display(); Enter nr or choice ( to abort): q里昄出的是整个工程中用到?display q个标识W的位置。此时输?4Q回车, 卛_跌{?main.c ?385 行调?display() 函数的地方进行浏览。浏览结束后?或? 可以回到跌{前的位置?/pre>
然后光标移动到源代码某个函数名上,q速地依次安下面的l合键:
s 其中 ?Ctrl-2 卛_输入。同P屏幕上出C一排结果,选择之后你会发现Q?br>跌{到的文g在水^方向的新H口中打开?/pre>
然后光标移动到源代码某个函数名上,q速地依次安下面的l合键:
s 选择之后你会发现Q蟩转到的文件将在垂直方向的新窗口中打开?/pre>
以上我们单介l了cscope的用方法,其中我们只用C一?s 命oQ即跟在 ?后面?s 键?br>同样Q我们可以用以下的功能键实C同的跌{功能?/pre>
c: 查找该函数被调用的位|? d: 查找该函数调用了哪些函数 e: 查找指定的正规表辑ּ f: 查找指定的文? g: 查找指定标识W的定义位置 i: 查找该文件在哪些地方被包? s: 查找指定标识W的使用位置 t: 查找指定的文本字W串 ↑ 命o行用说?† 除了上述通过快捷键映的方式使用cscope之外Q也可以直接在gvim命o行中使用cscope。这样就可以 随意定义查找字符Ԍ而不必局限于源代码中已有的标识符。命令格式如下:
:cscope find <关键?gt; 该命令可以羃写ؓ
:cs f <关键?gt; 一个比较实用的技巧是使用cscope打开文g。用以下命令即可直接打开名ؓdisplay.c的文Ӟ 而不必先切换到display.c所在的目录?/pre>
:cs f f display.c cscope也支持正规表辑ּ。如果记不清某个函数的名Uͼ可以用下面的方式来找到该函数的定义位|?/pre>
:cs f g .*SetConfiguration.* ↑ 版权 † Cscope虽然不是GPL版权Q但是Cscope是开放源码的自由软gQ用Cscope无须支付M费用?/pre>
↑ 参?† Cscope官方主页, http://cscope.sourceforge.net/ The Vim/Cscope tutorial, http://cscope.sourceforge.net/cscope_vim_tutorial.html Cscope on Win32, http://iamphet.nm.ru/cscope/ Vim中关?cscope 的帮助,使用 :help cscope 命o查看 ]]> Windows Socket五种I/O模型——代码全ȝQ下Q?/title> http://www.shnenglu.com/kenwell/archive/2010/08/03/122086.htmlc++ 学习 c++ 学习 Tue, 03 Aug 2010 09:27:00 GMT http://www.shnenglu.com/kenwell/archive/2010/08/03/122086.html http://www.shnenglu.com/kenwell/comments/122086.html http://www.shnenglu.com/kenwell/archive/2010/08/03/122086.html#Feedback 0 http://www.shnenglu.com/kenwell/comments/commentRss/122086.html http://www.shnenglu.com/kenwell/services/trackbacks/122086.html 2.用完成例E方式实现的重叠I/O模型 #include <WINSOCK2.H> #include <stdio.h>
#define PORT 5150 #define MSGSIZE 1024
#pragma comment(lib, "ws2_32.lib")
typedef struct { WSAOVERLAPPED overlap; WSABUF Buffer; char szMessage[MSGSIZE]; DWORD NumberOfBytesRecvd; DWORD Flags; SOCKET sClient; }PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;
DWORD WINAPI WorkerThread(LPVOID); void CALLBACK CompletionROUTINE(DWORD, DWORD, LPWSAOVERLAPPED, DWORD);
SOCKET g_sNewClientConnection; BOOL g_bNewConnectionArrived = FALSE;
int main() { WSADATA wsaData; SOCKET sListen; SOCKADDR_IN local, client; DWORD dwThreadId; int iaddrSize = sizeof(SOCKADDR_IN);
// Initialize Windows Socket library WSAStartup(0x0202, &wsaData);
// Create listening socket sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Bind local.sin_addr.S_un.S_addr = htonl(INADDR_ANY); local.sin_family = AF_INET; local.sin_port = htons(PORT); bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));
// Listen listen(sListen, 3);
// Create worker thread CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);
while (TRUE) { // Accept a connection g_sNewClientConnection = accept(sListen, (struct sockaddr *)&client, &iaddrSize); g_bNewConnectionArrived = TRUE; printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); } }
DWORD WINAPI WorkerThread(LPVOID lpParam) { LPPER_IO_OPERATION_DATA lpPerIOData = NULL;
while (TRUE) { if (g_bNewConnectionArrived) { // Launch an asynchronous operation for new arrived connection lpPerIOData = (LPPER_IO_OPERATION_DATA)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PER_IO_OPERATION_DATA)); lpPerIOData->Buffer.len = MSGSIZE; lpPerIOData->Buffer.buf = lpPerIOData->szMessage; lpPerIOData->sClient = g_sNewClientConnection; WSARecv(lpPerIOData->sClient, &lpPerIOData->Buffer, 1, &lpPerIOData->NumberOfBytesRecvd, &lpPerIOData->Flags, &lpPerIOData->overlap, CompletionROUTINE); g_bNewConnectionArrived = FALSE; }
SleepEx(1000, TRUE); } return 0; }
void CALLBACK CompletionROUTINE(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags) { LPPER_IO_OPERATION_DATA lpPerIOData = (LPPER_IO_OPERATION_DATA)lpOverlapped; if (dwError != 0 || cbTransferred == 0) { // Connection was closed by client closesocket(lpPerIOData->sClient); HeapFree(GetProcessHeap(), 0, lpPerIOData); } else { lpPerIOData->szMessage[cbTransferred] = '\0'; send(lpPerIOData->sClient, lpPerIOData->szMessage, cbTransferred, 0); // Launch another asynchronous operation memset(&lpPerIOData->overlap, 0, sizeof(WSAOVERLAPPED)); lpPerIOData->Buffer.len = MSGSIZE; lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
WSARecv(lpPerIOData->sClient, &lpPerIOData->Buffer, 1, &lpPerIOData->NumberOfBytesRecvd, &lpPerIOData->Flags, &lpPerIOData->overlap, CompletionROUTINE); } }
用完成例E来实现重叠I/O比用事g通知单得多。在q个模型中,ȝE只用不停的接受q接卛_Q辅助线E判断有没有新的客户端连接被建立Q如果有Q就为那个客L套接字激zM个异步的WSARecv操作Q然后调用SleepEx使线E处于一U可警告的等待状态,以得I/O完成后CompletionROUTINE可以被内核调用。如果辅助线E不调用SleepExQ则内核在完成一ơI/O操作后,无法调用完成例程Q因为完成例E的q行应该和当初激zWSARecv异步操作的代码在同一个线E之内)?br style="line-height: normal; ">完成例程内的实现代码比较单,它取出接收到的数据,然后数据原不动的发送给客户端,最后重新激zd一个WSARecv异步操作。注意,在这里用C“N数据”。我们在调用WSARecv的时候,参数lpOverlapped实际上指向一个比它大得多的结构PER_IO_OPERATION_DATAQ这个结构除了WSAOVERLAPPED以外Q还被我们附加了~冲区的l构信息Q另外还包括客户端套接字{重要的信息。这P在完成例E中通过参数lpOverlapped拿到的不仅仅是WSAOVERLAPPEDl构Q还有后边尾随的包含客户端套接字和接收数据缓冲区{重要信息。这LC语言技巧在我后面介l完成端口的时候还会用到?/p>
?完成端口模型 “完成端口”模型是迄今ؓ止最为复杂的一UI/O模型。然而,假若一个应用程序同旉要管理ؓC多的套接字,那么采用q种模型Q往往可以辑ֈ最佳的pȝ性能Q但不幸的是Q该模型只适用于Windows NT和Windows 2000操作pȝ。因其设计的复杂性,只有在你的应用程序需要同时管理数百乃至上千个套接字的时候,而且希望随着pȝ内安装的CPU数量的增多,应用E序的性能也可以线性提升,才应考虑采用“完成端口”模型。要C的一个基本准则是Q假如要为Windows NT或Windows 2000开发高性能的服务器应用Q同时希望ؓ大量套接字I/Oh提供服务QWeb服务器便是这斚w的典型例子)Q那么I/O完成端口模型便是最佳选择Q(节选自《Windows|络~程》第八章Q?br style="line-height: normal; ">完成端口模型是我最喜爱的一U模型。虽然其实现比较复杂Q其实我觉得它的实现比用事g通知实现的重叠I/O单多了)Q但其效率是惊h的。我在T公司的时候曾l帮同事写过一个邮件服务器的性能试E序Q用的就是完成端口模型。结果表明,完成端口模型在多q接Q成千上万)的情况下Q仅仅依靠一两个辅助U程Q就可以辑ֈ非常高的吞吐量。下面我q是从代码说P #include <WINSOCK2.H> #include <stdio.h>
#define PORT 5150 #define MSGSIZE 1024
#pragma comment(lib, "ws2_32.lib")
typedef enum { RECV_POSTED }OPERATION_TYPE;
typedef struct { WSAOVERLAPPED overlap; WSABUF Buffer; char szMessage[MSGSIZE]; DWORD NumberOfBytesRecvd; DWORD Flags; OPERATION_TYPE OperationType; }PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;
DWORD WINAPI WorkerThread(LPVOID);
int main() { WSADATA wsaData; SOCKET sListen, sClient; SOCKADDR_IN local, client; DWORD i, dwThreadId; int iaddrSize = sizeof(SOCKADDR_IN); HANDLE CompletionPort = INVALID_HANDLE_VALUE; SYSTEM_INFO systeminfo; LPPER_IO_OPERATION_DATA lpPerIOData = NULL;
// Initialize Windows Socket library WSAStartup(0x0202, &wsaData);
// Create completion port CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
// Create worker thread GetSystemInfo(&systeminfo); for (i = 0; i < systeminfo.dwNumberOfProcessors; i++) { CreateThread(NULL, 0, WorkerThread, CompletionPort, 0, &dwThreadId); } // Create listening socket sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Bind local.sin_addr.S_un.S_addr = htonl(INADDR_ANY); local.sin_family = AF_INET; local.sin_port = htons(PORT); bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));
// Listen listen(sListen, 3);
while (TRUE) { // Accept a connection sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize); printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
// Associate the newly arrived client socket with completion port CreateIoCompletionPort((HANDLE)sClient, CompletionPort, (DWORD)sClient, 0); // Launch an asynchronous operation for new arrived connection lpPerIOData = (LPPER_IO_OPERATION_DATA)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PER_IO_OPERATION_DATA)); lpPerIOData->Buffer.len = MSGSIZE; lpPerIOData->Buffer.buf = lpPerIOData->szMessage; lpPerIOData->OperationType = RECV_POSTED; WSARecv(sClient, &lpPerIOData->Buffer, 1, &lpPerIOData->NumberOfBytesRecvd, &lpPerIOData->Flags, &lpPerIOData->overlap, NULL); }
PostQueuedCompletionStatus(CompletionPort, 0xFFFFFFFF, 0, NULL); CloseHandle(CompletionPort); closesocket(sListen); WSACleanup(); return 0; }
DWORD WINAPI WorkerThread(LPVOID CompletionPortID) { HANDLE CompletionPort=(HANDLE)CompletionPortID; DWORD dwBytesTransferred; SOCKET sClient; LPPER_IO_OPERATION_DATA lpPerIOData = NULL;
while (TRUE) { GetQueuedCompletionStatus( CompletionPort, &dwBytesTransferred, &sClient, (LPOVERLAPPED *)&lpPerIOData, INFINITE); if (dwBytesTransferred == 0xFFFFFFFF) { return 0; } if (lpPerIOData->OperationType == RECV_POSTED) { if (dwBytesTransferred == 0) { // Connection was closed by client closesocket(sClient); HeapFree(GetProcessHeap(), 0, lpPerIOData); } else { lpPerIOData->szMessage[dwBytesTransferred] = '\0'; send(sClient, lpPerIOData->szMessage, dwBytesTransferred, 0); // Launch another asynchronous operation for sClient memset(lpPerIOData, 0, sizeof(PER_IO_OPERATION_DATA)); lpPerIOData->Buffer.len = MSGSIZE; lpPerIOData->Buffer.buf = lpPerIOData->szMessage; lpPerIOData->OperationType = RECV_POSTED; WSARecv(sClient, &lpPerIOData->Buffer, 1, &lpPerIOData->NumberOfBytesRecvd, &lpPerIOData->Flags, &lpPerIOData->overlap, NULL); } } } return 0; }
首先Q说说主U程Q?br style="line-height: normal; ">1.创徏完成端口对象 2.创徏工作者线E(q里工作者线E的数量是按照CPU的个数来军_的,q样可以辑ֈ最x能Q?br style="line-height: normal; ">3.创徏监听套接字,l定Q监听,然后E序q入循环 4.在@环中Q我做了以下几g事情Q?br style="line-height: normal; ">(1).接受一个客Lq接 (2).该客户端套接字与完成端口绑定到一?q是调用CreateIoCompletionPortQ但q次的作用不?Q注意,按道理来Ԍ此时传递给CreateIoCompletionPort的第三个参数应该是一个完成键Q一般来ԌE序都是传递一个单句柄数据l构的地址Q该单句柄数据包含了和该客户端连接有关的信息Q由于我们只兛_套接字句柄,所以直接将套接字句柄作为完成键传递; (3).触发一个WSARecv异步调用Q这ơ又用到?#8220;N数据”Q接收数据所用的~冲区紧跟在WSAOVERLAPPED对象之后Q此外,q有操作cd{重要信息?br style="line-height: normal; "> 在工作者线E的循环中,我们 1.调用GetQueuedCompletionStatus取得本次I/O的相关信息(例如套接字句柄、传送的字节数、单I/O数据l构的地址{等Q?br style="line-height: normal; ">2.通过单I/O数据l构扑ֈ接收数据~冲区,然后数据原不动的发送到客户?br style="line-height: normal; ">3.再次触发一个WSARecv异步操作
?五种I/O模型的比?br style="line-height: normal; ">我会从以下几个方面来q行比较 *有无每线E?4q接数限?br style="line-height: normal; ">如果在选择模型中没有重新定义FD_SETSIZE宏,则每个fd_set默认可以装下64个SOCKET。同LQ受MAXIMUM_WAIT_OBJECTS宏的影响Q事仉择、用事g通知实现的重叠I/O都有每线E最?4q接数限制。如果连接数成千上万Q则必须对客L套接字进行分l,q样Q势必增加程序的复杂度?br style="line-height: normal; ">相反Q异步选择、用完成例程实现的重叠I/O和完成端口不受此限制?/p>
*U程?br style="line-height: normal; ">除了异步选择以外Q其他模型至需?个线E。一个主U程和一个辅助线E。同LQ如果连接数大于64Q则选择模型、事仉择和用事g通知实现的重叠I/O的线E数q要增加?/p>
*实现的复杂度 我的个h看法是,在实现难度上Q异步选择<选择<用完成例E实现的重叠I/O<事g选择<完成端口<用事仉知实现的重叠I/O
*性能 ׃选择模型中每ơ都要重设读集,在select函数q回后还要针Ҏ有套接字q行逐一试Q我的感觉是效率比较差;完成端口和用完成例程实现的重叠I/O基本上不涉及全局数据Q效率应该是最高的Q而且在多处理器情形下完成端口q要高一些;事g选择和用事g通知实现的重叠I/O在实现机制上都是采用WSAWaitForMultipleEventsQ感觉效率差不多Q至于异步选择Q不好比较。所以我的结论是:选择<用事仉知实现的重叠I/O<事g选择<用完成例E实现的重叠I/O<完成端口
]]>Windows Socket五种I/O模型——代码全ȝQ上Q?/title> http://www.shnenglu.com/kenwell/archive/2010/08/03/122085.htmlc++ 学习 c++ 学习 Tue, 03 Aug 2010 09:26:00 GMT http://www.shnenglu.com/kenwell/archive/2010/08/03/122085.html http://www.shnenglu.com/kenwell/comments/122085.html http://www.shnenglu.com/kenwell/archive/2010/08/03/122085.html#Feedback 0 http://www.shnenglu.com/kenwell/comments/commentRss/122085.html http://www.shnenglu.com/kenwell/services/trackbacks/122085.html 阅读全文 ]]> 很幽默的讲解六种Socket I/O模型(转蝲Q?/title> http://www.shnenglu.com/kenwell/archive/2010/08/03/122069.htmlc++ 学习 c++ 学习 Tue, 03 Aug 2010 07:50:00 GMT http://www.shnenglu.com/kenwell/archive/2010/08/03/122069.html http://www.shnenglu.com/kenwell/comments/122069.html http://www.shnenglu.com/kenwell/archive/2010/08/03/122069.html#Feedback 0 http://www.shnenglu.com/kenwell/comments/commentRss/122069.html http://www.shnenglu.com/kenwell/services/trackbacks/122069.html 阅读全文 ]]> shell 变量间接引用 http://www.shnenglu.com/kenwell/archive/2010/08/02/121977.htmlc++ 学习 c++ 学习 Mon, 02 Aug 2010 08:46:00 GMT http://www.shnenglu.com/kenwell/archive/2010/08/02/121977.html http://www.shnenglu.com/kenwell/comments/121977.html http://www.shnenglu.com/kenwell/archive/2010/08/02/121977.html#Feedback 0 http://www.shnenglu.com/kenwell/comments/commentRss/121977.html http://www.shnenglu.com/kenwell/services/trackbacks/121977.html q种使用间接引用的方法是一个小技? 如果W二个变量更改了它的? 那么W一个变?/div>必须被适当的解除引?像上边的例子一?. q运的是, 在Bash版本2中引?/div>
?{!variable}形式使得使用间接引用更加直观?
假设一个变量的值是W二个变量的名字. 那么我们如何从第一个变量中取得W二个变量的值呢? 比如,
如果a=letter_of_alphabetq且letter_of_alphabet=z, 那么我们能够通过引用变量a来获得z? q确
实是可以做到? 它被UCؓ间接引用. 它用eval var1=\$$var2q种不^常的形式.
]]>
Linux Shell Bash 正则表达式介l?/title> http://www.shnenglu.com/kenwell/archive/2010/06/30/119014.htmlc++ 学习 c++ 学习 Wed, 30 Jun 2010 14:15:00 GMT http://www.shnenglu.com/kenwell/archive/2010/06/30/119014.html http://www.shnenglu.com/kenwell/comments/119014.html http://www.shnenglu.com/kenwell/archive/2010/06/30/119014.html#Feedback 1 http://www.shnenglu.com/kenwell/comments/commentRss/119014.html http://www.shnenglu.com/kenwell/services/trackbacks/119014.html 正则表达式就是由一pdҎ字符l成的字W串, 其中每个Ҏ字符都被UCؓ元字W?/em>, q些元字W?/em>q不表示为它们字面上的含?
而会被解释ؓ一些特定的含义. 具个例子, 比如引用W号, 可能是表示某h的演讲内? 同上 , 也可能表CZؓ我们下面要讲到的符L?含义.
正则表达式其实是由普通字W和元字W共同组成的集合, q个集合用来匚w(或指?模式.
一个正则表辑ּ会包含下列一Ҏ多项:
一个字W集 . q里所指的字符集只包含普通字W? q些字符只表C它们的字面含义.
正则表达式的最单Ş式就?em>?/em>包含字符? 而不包含元字W?
?/em>. ?/em>指定了正则表辑ּ所要匹配的文本在文本行中所处的位置. 比如, ^ , ?span class="TOKEN">$是?
修饰W?/em>. 它们扩大或羃?修改 )了正则表辑ּ匚w文本的范? 修饰W包含星? 括号,
和反斜杠.
正则表达式最主要的目的就是用?RE )文本搜烦与字W串操作. (译者注:
以下正则表达式也会被UCؓRE .) RE能够匚w 单个字符或者一个字W集 -- ?
一个字W串, 或者一个字W串的一部分.
星号 -- * -- 用来匚w它前面字W的L多次, 包括0?/em>.
"1133*" 匚w11 + 一个或多个3 +
也允许后边还有其他字W?/em> : 113 , 1133 , 111312 , {等.
?-- . -- 用于匚wL一个字W? 除了换行W?
"13." 匚w13 +
臛_一个Q意字W?包括I格) : 1133 , 11333 , 但不能匹?tt class="REPLACEABLE">13 (因ؓ~少"."所能匹配的臛_一个Q意字W?.
脱字W号 -- ^ -- 匚w行首, 但是某些时候需要依赖上下文环境, 在RE?
有时候也表示对一个字W集取反.
元W?-- $ -- 在RE中用来匹配行?
"XXX$" 匚w行尾?em>XXX
.
"^$" 匚wI.
中括?-- [...] -- 在RE? 匹配中括号字符集中的某一个字W?
"[xyz]" 会匚w字符x ,
y , ?tt class="REPLACEABLE">z .
"[c-n]" 匚w字符c 到字W?tt class="REPLACEABLE">n 之间的Q意一个字W?
"[B-Pk-y]" 匚w?tt class="REPLACEABLE">B ?tt class="REPLACEABLE">P , 或者从k ?tt class="REPLACEABLE">y 之间的Q意一个字W?
"[a-z0-9]" 匚wL写字母或数?
"[^b-d]" 会匚w范围?tt class="REPLACEABLE">b ?tt class="REPLACEABLE">d 之外?/em>L一个字W? q就是?span class="TOKEN">^对字W集取反的一个实? (好像在某些情况? ! 所表达的含?.
多个中括号字符集组合? 能够匚w一般的单词或数? "[Yy][Ee][Ss]" 能够匚wyes , Yes ,
YES , yEs , {等. "[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]"
可以匚wC保?Social Security number).
反斜?-- \ -- 用来转义 某个Ҏ含义的字W?
q意味着, q个Ҏ字符会被解释ؓ字面含义.
"\$" 会被解释成字符"$" ,
而不是RE中匹配行Ҏ字符. 怼? "\\" 会被解释ؓ字符"\" .
转义 ?span class="QUOTE">"括? -- \<...\> -- 用于匚w单词边界.
括号必被转义才含有特D的含义, 否则它就表示括L字面含义.
"\<the\>" 完整匚w单词"the" , 不会匚w"them" , "there" , "other" , {等.
bash$ cat textfile This is line 1, of which there is only one instance. This is the only instance of line 2. This is line 3, another line. This is line 4. bash$ grep 'the' textfile This is line 1, of which there is only one instance. This is the only instance of line 2. This is line 3, another line. bash$ grep '\<the\>' textfile This is the only instance of line 2.
问号 -- ? -- 匚w它前面的字符, 但是只能匚w1ơ或0? 通常用来匚w单个字符.
加号 -- + -- 匚w它前面的字符, 能够匚w一ơ或多次. 与前面讲?span class="TOKEN">*号作用类? 但是不能 匚w0个字W的情况.
1 # GNU版本的sed和awk能够使用"+", 2 # 但是它需要被转义一? 3 4 echo a111b | sed -ne '/a1\+b/p' 5 echo a111b | grep 'a1\+b' 6 echo a111b | gawk '/a1+b/' 7 # 上边3句的作用相同. 8 9 # 感谢, S.C.
转义 "大括? -- \{ \} -- 在{义后的大括号中加上一个数?
q个数字是它前面的RE所能匹配的ơ数.
大括号必ȝq{? 否则, 大括号仅仅表C字面含? q种用法q不是基本RE集合中的一部分, 仅仅是个技巧而以.
"[0-9]\{5\}" _匚w5个数?(所匚w的字W范围是0?).
使用大括号Ş式的RE是不能够?span class="QUOTE">"l典"(非POSIX兼容)?a >awk版本中正常运行的.
然? gawk 命o中有一?code class="OPTION">--re-interval选项, 使用q个选项允怋用大括号形式的RE?无需转义).
bash$ echo 2222 | gawk --re-interval '/2{3}/' 2222
Perl 与某些版本的egrep 不需要{义大括号.
圆括?-- ( ) -- 括v一l正则表辑ּ. 当你想?a >exprq行子字W串提取(substring
extraction) 的时? 圆括号就有用? 如果和下面要讲的"| " 操作W结合? 也非常有?
竖线 -- | -- 是RE中的"? 操作W? 使用它能够匹配一l可选字W中的Q意一?
bash$ egrep 're(a|e)d' misc.txt People who read seem to be better informed than those who do not. The clarinet produces sound by the vibration of its reed.
与GNU工具一? 某些版本?strong class="COMMAND">sed, ed , ?strong class="COMMAND">ex一栯够支持扩展正则表辑ּ,
上边q部分就描述了扩展正则表辑ּ.
q是另外一U? 用于指定匚w字符范围的方?
[:alnum:] 匚w字母和数? {h?kbd class="USERINPUT">A-Za-z0-9.
[:alpha:] 匚w字母. {h?kbd class="USERINPUT">A-Za-z.
[:blank:] 匚w一个空格或是一个制表符(tab).
[:cntrl:] 匚w控制字符.
[:digit:] 匚w(十进?数字. {h?kbd class="USERINPUT">0-9.
[:graph:] (可打印的囑Ş字符). 匚wASCII码D围在33 - 126之间的字W?
与下面所提到?kbd class="USERINPUT">[:print:]cM, 但是不包括空格字W?I格字符的ASCII码是32).
[:lower:] 匚w写字母. {h?kbd class="USERINPUT">a-z.
[:print:] (可打印的囑Ş字符). 匚wASCII码D围在32 - 126之间的字W?
与上边的[:graph:] cM, 但是包含I格.
[:space:] 匚wI白字符(I格和水q_表符).
[:upper:] 匚w大写字母. {h?kbd class="USERINPUT">A-Z.
[:xdigit:] 匚w16q制数字. {h?kbd class="USERINPUT">0-9A-Fa-f.
POSIX字符c通常都要用引h双中括号 ([[
]])引v?
bash$ grep [[:digit:]] test.file abc=723
如果在一个受限的范围? q些字符cȝ臛_以用?a >通配(globbing)?
bash$ ls -l ?[[:digit:]][[:digit:]]? -rw-rw-r-- 1 bozo bozo 0 Aug 21 14:47 a33b
如果想了解POSIX字符cd脚本中的使用情况, 请参?a >例子
12-18?a >例子
12-19.
Sed ,
awk ,
?a >Perl在脚本中一般都被用作过滤器,
q些qo器将会以RE为参? Ҏ件或者I/O进?qo"或{? 请参?a >例子
A-12?a >例子
A-17, 来详l了解这U用?
对于REq个复杂的主? 标准的参考材料是Friedl?em class="CITETITLE">Mastering Regular
Expressions
. 由Dougherty和Robbins所~写?em class="CITETITLE">Sed &
Awkq本? 也对REq行了清晰的. 如果惌得这些书的更多信? 请察?a >参考文?/em>.
]]> shell术表达式操作方法汇?/title> http://www.shnenglu.com/kenwell/archive/2010/06/28/118870.htmlc++ 学习 c++ 学习 Mon, 28 Jun 2010 09:03:00 GMT http://www.shnenglu.com/kenwell/archive/2010/06/28/118870.html http://www.shnenglu.com/kenwell/comments/118870.html http://www.shnenglu.com/kenwell/archive/2010/06/28/118870.html#Feedback 0 http://www.shnenglu.com/kenwell/comments/commentRss/118870.html http://www.shnenglu.com/kenwell/services/trackbacks/118870.html 1.
expr expression
expr 只能用于一元操作符 , 不支持二元操作符
1 x= 1
2 x=$(expr $x + 1)
$x + 1 之间必须有空?/span>
2.
let expression
let 的用方?/span>
x=10
let x=$x+1
let x+=1
let x*=10
{?/span>
Let 没有q回?/span>
3.
使用 $((expression )) ?/span> ((expression)) 形式
((expression)) 的用方?/span>
x=10
((x+=10))
(( expression)) 用法?/span>let cM
$(()) 的用用?/span>
Q?/span> $((x=$x+10))
echo $x
y=$((x=$x-10))
echo $y
y=$(($x+1))
echo $y
echo $x
4.
使用 $[
] 形式
例如Q?/span>
n=1
: $[
n=$n+1 ]( Q和 $ 之间有空?/span>)
y=$[ n = $n + 1 ]
echo $y
y=$[ $n+1 ]
echo $y
5.
使用 decalare
例子Q?/span>
decare –i num
num=$num+1
echo $num
]]> Bash Process Substitution(shell q程替换Q?/title> http://www.shnenglu.com/kenwell/archive/2010/06/27/118826.htmlc++ 学习 c++ 学习 Sun, 27 Jun 2010 09:15:00 GMT http://www.shnenglu.com/kenwell/archive/2010/06/27/118826.html http://www.shnenglu.com/kenwell/comments/118826.html http://www.shnenglu.com/kenwell/archive/2010/06/27/118826.html#Feedback 0 http://www.shnenglu.com/kenwell/comments/commentRss/118826.html http://www.shnenglu.com/kenwell/services/trackbacks/118826.html Bash Process Substitution In addition to the fairly common forms of input/output redirection the shell recognizes something called process substitution . Although not documented as a form of input/output redirection, its syntax and its effects are similar.
The syntax for process substitution is:
<(list)
or
>(list)
where each
list is a command or a pipeline of commands. The effect of process substitution is to make each list act like a file. This is done by giving the list a
name in the file system and then substituting that name in the command line. The list is given a name either by connecting the list to named pipe or by using a file in
/dev/fd (if supported by the O/S). By doing this, the command simply sees a file name and is unaware that its reading from or writing to a command pipeline.
To substitute a command pipeline for an input file the syntax is:
command ... <(list) ...
To substitute a command pipeline for an output file the syntax is:
command ... >(list) ...
At first process substitution may seem rather pointless, for example you might imagine something simple like:
uniq <(sort a)
to sort a file and then find the unique lines in it, but this is more commonly (and more conveniently) written as:
sort a | uniq
The power of process substitution comes when you have multiple command pipelines that you want to connect to a single command.
For example, given the two files:
# cat a
e
d
c
b
a
# cat b
g
f
e
d
c
b
To view the lines unique to each of these two unsorted files you might do something like this:
# sort a | uniq >tmp1
# sort b | uniq >tmp2
# comm -3 tmp1 tmp2
a
f
g
# rm tmp1 tmp2
With process substitution we can do all this with one line:
# comm -3 <(sort a | uniq) <(sort b | uniq)
a
f
g
Depending on your shell settings you may get an error message similar to:
syntax error near unexpected token `('
when you try to use process substitution, particularly if you try to use it within a shell script. Process substitution is not a POSIX compliant feature and so it may have to be enabled via:
set +o posix
Be careful not to try something like:
if [[ $use_process_substitution -eq 1 ]]; then
set +o posix
comm -3 <(sort a | uniq) <(sort b | uniq)
fi
The command
set +o posix enables not only the execution of process substitution but the recognition of the syntax. So, in the example above the shell tries to parse the process substitution syntax before the "set" command is executed and therefore still sees the process substitution syntax as illegal.
Of course, note that all shells may not support process substitution, these examples will work with bash.
q程替换与命令替换很怼. 命o替换把一个命令的l果赋值给一个变? 比如dir_contents=`ls -
al`或xref=$( grep word datafile). q程替换把一个进E的输出提供l另一个进E?换句话说, 它把
一个命令的l果发给了另一个命?.
命o替换的模?/p>
用圆括号扩v来的命o
>(command)
<(command)
启动q程替换. 它?dev/fd/<n>文g圆括号中的q程处理l果发送给另一个进E? [1] (?/p>
者注: 实际上现代的UNIXcL作系l提供的/dev/fd/n文g是与文g描述W相关的, 整数n指的?/p>
是进E运行时对应数字的文件描q符)
?<"?>"与圆括号之间是没有空格的. 如果加了I格, 会生错?
bash$ echo >(true)
/dev/fd/63
bash$ echo <(true)
/dev/fd/63
Bash在两个文件描q符之间创徏了一个管? --fIn和fOut--. true命o的stdin被连接到fOut
(dup2(fOut, 0)), 然后Bash?dev/fd/fIn作ؓ参数传给echo. 如果pȝ~Z/dev/fd/<n>文g, Bash?/p>
使用临时文g. (感谢, S.C.)
q程替换可以比较两个不同命o的输? 甚至能够比较同一个命令不同选项情况下的输出.
bash$ comm <(ls -l) <(ls -al)
total 12
-rw-rw-r-- 1 bozo bozo 78 Mar 10 12:58 File0
-rw-rw-r-- 1 bozo bozo 42 Mar 10 12:58 File2
-rw-rw-r-- 1 bozo bozo 103 Mar 10 12:58 t2.sh
total 20
drwxrwxrwx 2 bozo bozo 4096 Mar 10 18:10 .
drwx------ 72 bozo bozo 4096 Mar 10 17:58 ..
-rw-rw-r-- 1 bozo bozo 78 Mar 10 12:58 File0
-rw-rw-r-- 1 bozo bozo 42 Mar 10 12:58 File2
-rw-rw-r-- 1 bozo bozo 103 Mar 10 12:58 t2.sh
使用q程替换来比较两个不同目录的内容(可以查看哪些文g名相? 哪些文g名不?:
1 diff <(ls $first_directory) <(ls $second_directory)
一些进E替换的其他用法与技?
1 cat <(ls -l)
2 # {h?ls -l | cat
3
4 sort -k 9 <(ls -l /bin) <(ls -l /usr/bin) <(ls -l /usr/X11R6/bin)
5 # 列出pȝ3个主?bin'目录中的所有文? q且按文件名q行排序.
6 # 注意??查一? 上面?个圆括号)明显不同的命令输Z递给'sort'.
7
8
9 diff <(command1) <(command2) # l出两个命o输出的不同之?
10
11 tar cf >(bzip2 -c > file.tar.bz2) $directory_name
12 # 调用"tar cf /dev/fd/?? $directory_name", ?bzip2 -c > file.tar.bz2".
13 #
14 # 因ؓ/dev/fd/<n>的系l属?
15 # 所以两个命令之间的道不必被命?
16 #
17 # q种效果可以被模拟出?
18 #
19 bzip2 -c < pipe > file.tar.bz2&
20 tar cf pipe $directory_name
21 rm pipe
22 # ?/p>
23 exec 3>&1
24 tar cf /dev/fd/4 $directory_name 4>&1 >&3 3>&- | bzip2 -c > file.tar.bz2 3>&-
25 exec 3>&-
26
27
28 # 感谢, Stephane Chazelas
一个读者给我发了一个有的例子, 是关于进E替换的, 如下.
1 # 摘自SuSE发行版中的代码片?
2
3 while read des what mask iface; do
4 # q里省略了一些命?..
5 done < <(route -n)
6
7
8 # Z试? 我们让它做点?
9 while read des what mask iface; do
10 echo $des $what $mask $iface
11 done < <(route -n)
12
13 # 输出:
14 # Kernel IP routing table
15 # Destination Gateway Genmask Flags Metric Ref Use Iface
16 # 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo
17
18
19
20 # 像Stephane Chazelas所l出的那? 一个更Ҏ理解的等价代码是:
21 route -n |
22 while read des what mask iface; do # 道的输赋值给了变?
23 echo $des $what $mask $iface
24 done # q将产生Z上边相同的输?
25 # 然? Ulrich Gayer指出 . . .
26 #+ q个单的{h版本在while循环中用了一个子shell,
27 #+ 因此当管道结束后, 变量消׃.
28
29
30
31 # 更进一? Filip Moritz解释了上面两个例子之间存在一个细微的不同之处,
32 #+ 如下所C?
33
34 (
35 route -n | while read x; do ((y++)); done
36 echo $y # $y 仍然没有被声明或讄
37
38 while read x; do ((y++)); done < <(route -n)
39 echo $y # $y 的gؓroute -n的输?
40 )
41
42 # 一般来? (译者注: 原书作者在q里q未加注释符?#", 应该是笔?
43 (
44 : | x=x
45 # 看上L启动了一个子shell
46 : | ( x=x )
47 # ?/p>
48 x=x < <(:)
49 # 其实不是
50 )
51
52 # 当你要解析csv或类g西的时侯, q非常有?
53 # 事实? q就是SuSE的这个代码片断所要实现的功能.
注意事项
[1] q与命名道(临时文g)h相同的作? q且, 事实? 命名道也被同时使用在进E?/p>
替换?
]]> 关于bash的管道与q程的几个知识点 http://www.shnenglu.com/kenwell/archive/2010/06/25/118723.htmlc++ 学习 c++ 学习 Fri, 25 Jun 2010 08:35:00 GMT http://www.shnenglu.com/kenwell/archive/2010/06/25/118723.html http://www.shnenglu.com/kenwell/comments/118723.html http://www.shnenglu.com/kenwell/archive/2010/06/25/118723.html#Feedback 0 http://www.shnenglu.com/kenwell/comments/commentRss/118723.html http://www.shnenglu.com/kenwell/services/trackbacks/118723.html 几个知识?br style="word-wrap: break-word; line-height: normal; ">1.Bash在实现pipeline(道|)时会发v两个subshell (子shell)来运行|两边?span href="tag.php?name=%C3%FC%C1%EE" class="t_tag" style="word-wrap: break-word; line-height: normal; cursor: pointer; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(255, 0, 0); white-space: nowrap; ">命oQ对?span href="tag.php?name=%CF%B5%CD%B3" class="t_tag" style="word-wrap: break-word; line-height: normal; cursor: pointer; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(255, 0, 0); white-space: nowrap; ">pȝ来说是发v两个childprocess(子进E) 2.fork是生process的唯一途径Qexec*是执行程序的唯一途径 3.子进E会完全复制父进E,除了$PID?PPID 4.fork子进E时l承父进E的q程名,在exec*执行命o时才由exec*替换为子q程对应的命令,同一q程的命令名可以׃个个exec*L多次的改?/strong> [注]对于linux q_ QJB上就是这LQ其它^C好发表意见,当然对于2中的两个唯一有一个例外,是在kenerl init的初? 暂时找不到相兛_考,也没有功力读源码Q所以此论是道听途说U别Q错误之处请指出ҎQ如果没有改正的价值可一W而过我觉得要先弄清楚sub shell的定义?br style="word-wrap: break-word; line-height: normal; "> 查了些资料,发现subshell的定义有些乱?br style="word-wrap: break-word; line-height: normal; ">bashMan:Each command in a pipeline is executed as a separate process (i.e., in a subshell).
When a simple command other than a builtin or shell function is to be executed, it is invoked in a separate execution environment that consists of the following. Unless otherwise noted, the values are inherited from the shell.
q个separate execution是subshell吗? A. 在当前shell执行外部命oQ如shell> date, 是fork+exec, 不是subshell? B. ()是fork一个child shellQ该child再fork+exec来执行命令。这个subshell和A中的"subshell"昄是不同的?br style="word-wrap: break-word; line-height: normal; "> UNIX: The Textbook, by Syed Mansoor Sarvar, Robert Koretsky and Syed Aqeel Sarvar中提刎ͼA child shell is also called subshell
问题是fork+exec是fork一个child shellQ然后在该child shell中exec. 而执行脚?shell>scriptname)Ӟ是fort一个child shell AQ该child shell A再fork一个child shell B, 在B中再exec. 那么child shell是指哪种情况Q?br style="word-wrap: break-word; line-height: normal; "> UNIX at Fermilab中的Important UNIX Concepts:When you give the shell a command associated with a compiled executable or shell script, the shell creates, or forks, a new process called a subshell.
外部命o也在subshell中执行?br style="word-wrap: break-word; line-height: normal; ">To execute most built-in commands, the shell forks a subshell which executes the command directly (no exec system call). For the built-in commands cd, set, alias and source, the current shell executes the command; no subshell is forked.
shell> built-inCommandsq样执行Ӟ大部分内部命令也是在subshell中执行?br style="word-wrap: break-word; line-height: normal; ">可见QUNIX at Fermilab认ؓfork 一个child shell是subshell, 不管是fork-fork+exec, q是 fork+exec?br>我刚才又ȝ了下ABSQ定义与我的理解不一?br style="word-wrap: break-word; line-height: normal; ">A subshell is a separate instance of the command processor -- the shell that gives you the prompt at the console or in an xterm window. Just as your commands are interpreted at the command line prompt, similarly does a script batch-process a list of commands. Each shell script running is, in effect, a subprocess (child process) of the parent shell.
./script也是external_cmd的一U啊Q都是fork-execQ至于external-cmd再作什么动作完全是external-cmd?/td>
]]>shell metacharacters 与IFS讨论 http://www.shnenglu.com/kenwell/archive/2010/06/25/118721.htmlc++ 学习 c++ 学习 Fri, 25 Jun 2010 08:29:00 GMT http://www.shnenglu.com/kenwell/archive/2010/06/25/118721.html http://www.shnenglu.com/kenwell/comments/118721.html http://www.shnenglu.com/kenwell/archive/2010/06/25/118721.html#Feedback 0 http://www.shnenglu.com/kenwell/comments/commentRss/118721.html http://www.shnenglu.com/kenwell/services/trackbacks/118721.html good job!^算有h看得懂了?/span>不過Q要細說的話Q要扯上 shell ?interpret 一?command line 時的 priority ?/span>基本上,光序如下: 1Q將 line 拆成 words QIFS很重要) 2Q括?alias 3Q擴???/span>4Q擴?~ 5Q擴?$variable, $(command), `command` 6Q重i再拆成 words 7Q括?wildcards 8Q處?I/O redirection 9Q載入命令運?/span>如果大家有O'Reilly英文版的 Learning the Bash(2nd)的話Q請多端詳p178的圖Q細略異Q?/span>回到LZ的問,看上?5 ?6 的順序然後才?9 ?/span>也就是在 6 重組命o?$A 已經完成替換Q當時的 environment 是沒賦| 因此重組後就?A=B echo 然後在第 9 的步驟運行命令時Q?A=B 是 echo 命o?local environmentQ?/span>不管是否 built-in commandQ都不媄響當前的 shell Q不同的 shell 在實作上或有差異Q?/span>所以第二行?echo $A 也是得到沒c?/span>
我通过eval说明赋值是成功的,而不?5楼所说的赋g成功?br style="word-wrap: break-word; line-height: normal; "> W一步?metacharacterQ与IFS没有关系
The following is a brief description of the shell's operation when it reads and executes a command. Basically, the shell does the following: 1. Reads its input from a file (*note Shell Scripts::), from a string supplied as an argument to the `-c' invocation option (*note Invoking Bash::), or from the user's terminal. 2. Breaks the input into words and operators, obeying the quoting rules described in *Note Quoting::. These tokens are separated by `metacharacters'. Alias expansion is performed by this step (*note Aliases::).
`IFS' A list of characters that separate fields; used when the shell splits words as part of expansion.
`metacharacter' A character that, when unquoted, separates words. A metacharacter is a `blank' or one of the following characters: `|', `&', `;', `(', `)', `<', or `>'.
8.05 命o行的评hQevaluationQ?br style="word-wrap: break-word; line-height: normal; ">下面是C shell 解释命o行的序Q?br style="word-wrap: break-word; line-height: normal; ">1. 历史替换 2. 分裂词(包括Ҏ字符Q?br style="word-wrap: break-word; line-height: normal; ">3. 更新历史?br style="word-wrap: break-word; line-height: normal; ">4. 解释单引P'Q??双引P"Q?br style="word-wrap: break-word; line-height: normal; ">5. 别名替换 6. 输入和输出的重定向(?> < ?|Q?br style="word-wrap: break-word; line-height: normal; ">7. 变量替换 8. 命o替换 9. 文g名扩?br style="word-wrap: break-word; line-height: normal; ">QBourne shell 的解释顺序本质上是一LQ除了它不执行历史替换和别名替换之外Q?br style="word-wrap: break-word; line-height: normal; "> 所?br style="word-wrap: break-word; line-height: normal; ">A=B echo $A 的执行过E应该是q样的: 1. 没有历史操作W, 因此不进行历史替换(Bourne shell 不执行这一步) 2. 分裂词,每碰到未加引LI白字符׃产生一个新“?#8221;。这些词?A=B、echo?A?br style="word-wrap: break-word; line-height: normal; ">3. shell 命令行攑ֈ历史列表中。(Bourne shell 不执行这一步) 4. 没有引号需要解?br style="word-wrap: break-word; line-height: normal; ">5. 没有别名需要替?br style="word-wrap: break-word; line-height: normal; ">6. 没有输入或输出重定向需要处?br style="word-wrap: break-word; line-height: normal; ">7. shell注意到变?AQƈ把它替换成空 8. shellL左单引号Q执行左单引号中的Q何命令,q且命令的输出插入到命令行中。在本例中,没有q方面的事需要做。(如果左单引号内有通配W或者变量,那么在shellq行左单引号中的命o之前它们是不会被解释的) 9. shellL通配W。本例中没有Q不需要处?br style="word-wrap: break-word; line-height: normal; ">10. shell 执行 A=BQ?执行 echo ?/span>
8.05 命o行的评hQevaluationQ?br style="word-wrap: break-word; line-height: normal; ">下面是C shell 解释命o行的序Q?br style="word-wrap: break-word; line-height: normal; ">1. 历史替换 2. 分裂词(包括Ҏ字符Q?br style="word-wrap: break-word; line-height: normal; ">3. 更新历史?br style="word-wrap: break-word; line-height: normal; ">4. 解释单引P'Q??双引P"Q?br style="word-wrap: break-word; line-height: normal; ">5. 别名替换 6. 输入和输出的重定向(?> < ?|Q?br style="word-wrap: break-word; line-height: normal; ">7. 变量替换 8. 命o替换 9. 文g名扩?br style="word-wrap: break-word; line-height: normal; ">QBourne shell 的解释顺序本质上是一LQ除了它不执行历史替换和别名替换之外Q?br style="word-wrap: break-word; line-height: normal; "> 所?br style="word-wrap: break-word; line-height: normal; ">A=B echo $A 的执行过E应该是q样的: 1. 没有历史操作W, 因此不进行历史替换(Bourne shell 不执行这一步) 2. 分裂词,每碰到未加引LI白字符׃产生一个新“?#8221;。这些词?A=B、echo?A?br style="word-wrap: break-word; line-height: normal; ">3. shell 命令行攑ֈ历史列表中。(Bourne shell 不执行这一步) 4. 没有引号需要解?br style="word-wrap: break-word; line-height: normal; ">5. 没有别名需要替?br style="word-wrap: break-word; line-height: normal; ">6. 没有输入或输出重定向需要处?br style="word-wrap: break-word; line-height: normal; ">7. shell注意到变?AQƈ把它替换成空 8. shellL左单引号Q执行左单引号中的Q何命令,q且命令的输出插入到命令行中。在本例中,没有q方面的事需要做。(如果左单引号内有通配W或者变量,那么在shellq行左单引号中的命o之前它们是不会被解释的) 9. shellL通配W。本例中没有Q不需要处?br style="word-wrap: break-word; line-height: normal; ">10. shell 执行 A=BQ?执行 echo ?/span>
]]>
AVݺɫۺϾþ |
þþþþþۺ |
Ʒһþò |
˾þô߽AVɫɫ |
ŷһþþƷ |
ŷպĻþ |
ۿþ |
˾þô߽Ʒ |
91Ʒۿ91þþþþ |
þþƷ |
aëƬ÷˾þ |
һĻþ |
ձһƷþþþӰԺ |
˾þ |
þþƷĻһ |
þһҹ |
99Ʒþ |
þþþƷ |
91鶹Ʒ91þþ |
Ĺ˾Ʒþò |
ɫ͵͵͵þ˴ý |
7ŷպۺľþþþ |
˾Ʒþһav
|
94þùƷ |
Ʒþ66 |
Ļþۺ |
ŷһþ |
þþþ |
ɫվWWWþþž |
Ʒþþþþ |
þ붯aëƬ |
99þһ |
˾þóۺӰԺ |
ھƷþ |
þþƷ |
þþþþþþþþ |
ƷëٸAVѾþ
|
97ȾþƵƷ99 |
͵ٸþþþþþþ |
뾫Ʒþþ |
ģ˽ĹƷþ |