﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-关注编辑器的制作-文章分类-转贴收集</title><link>http://www.cppblog.com/megax/category/6330.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 07 Aug 2008 18:07:48 GMT</lastBuildDate><pubDate>Thu, 07 Aug 2008 18:07:48 GMT</pubDate><ttl>60</ttl><item><title>[转]字符转换</title><link>http://www.cppblog.com/megax/articles/58279.html</link><dc:creator>megax</dc:creator><author>megax</author><pubDate>Thu, 07 Aug 2008 12:18:00 GMT</pubDate><guid>http://www.cppblog.com/megax/articles/58279.html</guid><wfw:comment>http://www.cppblog.com/megax/comments/58279.html</wfw:comment><comments>http://www.cppblog.com/megax/articles/58279.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/megax/comments/commentRss/58279.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/megax/services/trackbacks/58279.html</trackback:ping><description><![CDATA[<p>一 C++ 中 string与wstring互转</p>
<p>方法一：</p>
<p>string WideToMutilByte(const wstring&amp; _src)<br>{<br>int nBufSize = WideCharToMultiByte(GetACP(), 0, _src.c_str(),-1, NULL, 0, 0, FALSE);</p>
<p>char *szBuf = new char[nBufSize];</p>
<p>WideCharToMultiByte(GetACP(), 0, _src.c_str(),-1, szBuf, nBufSize, 0, FALSE);</p>
<p>string strRet(szBuf);</p>
<p>delete []szBuf;<br>szBuf = NULL;</p>
<p>return strRet;<br>}</p>
<p>wstring MutilByteToWide(const string&amp; _src)<br>{<br>//计算字符串 string 转成 wchar_t 之后占用的内存字节数<br>int nBufSize = MultiByteToWideChar(GetACP(),0,_src.c_str(),-1,NULL,0); </p>
<p>//为 wsbuf 分配内存 BufSize 个字节<br>wchar_t *wsBuf = new wchar_t[nBufSize];</p>
<p>//转化为 unicode 的 WideString<br>MultiByteToWideChar(GetACP(),0,_src.c_str(),-1,wsBuf,nBufSize); </p>
<p>wstring wstrRet(wsBuf);</p>
<p>delete []wsBuf;<br>wsBuf = NULL;</p>
<p>return wstrRet;<br>}</p>
<p>&nbsp;</p>
<p><br>转载：csdn</p>
<p>这篇文章里，我将给出几种C++ std::string和std::wstring相互转换的转换方法。<br>&nbsp;<br>第一种方法：调用WideCharToMultiByte()和MultiByteToWideChar()，代码如下（关于详细的解释，可以参考《windows核心编程》）：<br>&nbsp;</p>
<p>#include &lt;string&gt;<br>#include &lt;windows.h&gt;<br>using namespace std;<br>//Converting a WChar string to a Ansi string<br>std::string WChar2Ansi(LPCWSTR pwszSrc)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int nLen = WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, NULL, 0, NULL, NULL);<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (nLen&lt;= 0) return std::string("");<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char* pszDst = new char[nLen];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (NULL == pszDst) return std::string("");<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, pszDst, nLen, NULL, NULL);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pszDst[nLen -1] = 0;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::string strTemp(pszDst);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete [] pszDst;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return strTemp;<br>}</p>
<p>&nbsp;<br>string ws2s(wstring&amp; inputws)<br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return WChar2Ansi(inputws.c_str()); <br>}</p>
<p>&nbsp;</p>
<p>&nbsp;<br>//Converting a Ansi string to WChar string </p>
<p><br>std::wstring Ansi2WChar(LPCSTR pszSrc, int nLen)<br>&nbsp;<br>{<br>&nbsp;&nbsp;&nbsp; int nSize = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszSrc, nLen, 0, 0);<br>&nbsp;&nbsp;&nbsp; if(nSize &lt;= 0) return NULL;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WCHAR *pwszDst = new WCHAR[nSize+1];<br>&nbsp;&nbsp;&nbsp; if( NULL == pwszDst) return NULL;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; MultiByteToWideChar(CP_ACP, 0,(LPCSTR)pszSrc, nLen, pwszDst, nSize);<br>&nbsp;&nbsp;&nbsp; pwszDst[nSize] = 0;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; if( pwszDst[0] == 0xFEFF)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // skip Oxfeff<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; nSize; i ++) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pwszDst[i] = pwszDst[i+1]; <br>&nbsp;<br>&nbsp;&nbsp;&nbsp; wstring wcharString(pwszDst);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete pwszDst;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; return wcharString;<br>}</p>
<p>&nbsp;<br>std::wstring s2ws(const string&amp; s)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp; return Ansi2WChar(s.c_str(),s.size());<br>}</p>
<p><br>&nbsp; <br>&nbsp;<br>第二种方法：采用ATL封装_bstr_t的过渡：（注，_bstr_是Microsoft Specific的，所以下面代码可以在VS2005通过，无移植性）；</p>
<p><br>#include &lt;string&gt;<br>#include &lt;comutil.h&gt;<br>using namespace std;<br>#pragma comment(lib, "comsuppw.lib") <br>&nbsp;<br>string ws2s(const wstring&amp; ws);<br>wstring s2ws(const string&amp; s);<br>&nbsp;<br>string ws2s(const wstring&amp; ws)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _bstr_t t = ws.c_str();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char* pchar = (char*)t;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string result = pchar;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return result;<br>}</p>
<p>&nbsp;<br>wstring s2ws(const string&amp; s)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _bstr_t t = s.c_str();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wchar_t* pwchar = (wchar_t*)t;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wstring result = pwchar;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return result;<br>}</p>
<p><br>&nbsp;<br>第三种方法：使用CRT库的mbstowcs()函数和wcstombs()函数，平台无关，需设定locale。</p>
<p><br>#include &lt;string&gt;<br>#include &lt;locale.h&gt;<br>using namespace std;<br>string ws2s(const wstring&amp; ws)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string curLocale = setlocale(LC_ALL, NULL);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // curLocale = "C";<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setlocale(LC_ALL, "chs"); <br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const wchar_t* _Source = ws.c_str();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t _Dsize = 2 * ws.size() + 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *_Dest = new char[_Dsize];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memset(_Dest,0,_Dsize);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcstombs(_Dest,_Source,_Dsize);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string result = _Dest;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete []_Dest;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setlocale(LC_ALL, curLocale.c_str());<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return result;<br>}</p>
<p>&nbsp;<br>wstring s2ws(const string&amp; s)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setlocale(LC_ALL, "chs"); <br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const char* _Source = s.c_str();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t _Dsize = s.size() + 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wchar_t *_Dest = new wchar_t[_Dsize];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wmemset(_Dest, 0, _Dsize);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mbstowcs(_Dest,_Source,_Dsize);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wstring result = _Dest;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete []_Dest;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setlocale(LC_ALL, "C");<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return result;<br>}</p>
<p><br>二 utf8.utf16.utf32的相互转化</p>
<p>可以参考Unicode.org 上有ConvertUTF.c和ConvertUTF.h （下载地址：<a href="http://www.unicode.org/Public/PROGRAMS/CVTUTF/">http://www.unicode.org/Public/PROGRAMS/CVTUTF/</a>）</p>
<p>实现文件ConvertUTF.c：（.h省）<br>/**//*<br>&nbsp;* Copyright 2001-2004 Unicode, Inc.<br>&nbsp;* <br>&nbsp;* Disclaimer<br>&nbsp;* <br>&nbsp;* This source code is provided as is by Unicode, Inc. No claims are<br>&nbsp;* made as to fitness for any particular purpose. No warranties of any<br>&nbsp;* kind are expressed or implied. The recipient agrees to determine<br>&nbsp;* applicability of information provided. If this file has been<br>&nbsp;* purchased on magnetic or optical media from Unicode, Inc., the<br>&nbsp;* sole remedy for any claim will be exchange of defective media<br>&nbsp;* within 90 days of receipt.<br>&nbsp;* <br>&nbsp;* Limitations on Rights to Redistribute This Code<br>&nbsp;* <br>&nbsp;* Unicode, Inc. hereby grants the right to freely use the information<br>&nbsp;* supplied in this file in the creation of products supporting the<br>&nbsp;* Unicode Standard, and to make copies of this file in any form<br>&nbsp;* for internal or external distribution as long as this notice<br>&nbsp;* remains attached.<br>&nbsp;*/</p>
<p>/**//* ---------------------------------------------------------------------</p>
<p>&nbsp;&nbsp;&nbsp; Conversions between UTF32, UTF-16, and UTF-8. Source code file.<br>&nbsp;&nbsp;&nbsp; Author: Mark E. Davis, 1994.<br>&nbsp;&nbsp;&nbsp; Rev History: Rick McGowan, fixes &amp; updates May 2001.<br>&nbsp;&nbsp;&nbsp; Sept 2001: fixed const &amp; error conditions per<br>&nbsp;&nbsp;&nbsp; mods suggested by S. Parent &amp; A. Lillich.<br>&nbsp;&nbsp;&nbsp; June 2002: Tim Dodd added detection and handling of incomplete<br>&nbsp;&nbsp;&nbsp; source sequences, enhanced error detection, added casts<br>&nbsp;&nbsp;&nbsp; to eliminate compiler warnings.<br>&nbsp;&nbsp;&nbsp; July 2003: slight mods to back out aggressive FFFE detection.<br>&nbsp;&nbsp;&nbsp; Jan 2004: updated switches in from-UTF8 conversions.<br>&nbsp;&nbsp;&nbsp; Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.</p>
<p>&nbsp;&nbsp;&nbsp; See the header file "ConvertUTF.h" for complete documentation.</p>
<p>------------------------------------------------------------------------ */</p>
<p><br>#include "ConvertUTF.h"<br>#ifdef CVTUTF_DEBUG<br>#include &lt;stdio.h&gt;<br>#endif</p>
<p>static const int halfShift&nbsp; = 10; /**//* used for shifting by 10 bits */</p>
<p>static const UTF32 halfBase = 0x0010000UL;<br>static const UTF32 halfMask = 0x3FFUL;</p>
<p>#define UNI_SUR_HIGH_START&nbsp; (UTF32)0xD800<br>#define UNI_SUR_HIGH_END&nbsp;&nbsp;&nbsp; (UTF32)0xDBFF<br>#define UNI_SUR_LOW_START&nbsp;&nbsp; (UTF32)0xDC00<br>#define UNI_SUR_LOW_END&nbsp;&nbsp;&nbsp;&nbsp; (UTF32)0xDFFF<br>#define false&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0<br>#define true&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1</p>
<p>/**//* --------------------------------------------------------------------- */</p>
<p>ConversionResult ConvertUTF32toUTF16 (<br>&nbsp;&nbsp;&nbsp; const UTF32** sourceStart, const UTF32* sourceEnd, <br>&nbsp;&nbsp;&nbsp; UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {<br>&nbsp;&nbsp;&nbsp; ConversionResult result = conversionOK;<br>&nbsp;&nbsp;&nbsp; const UTF32* source = *sourceStart;<br>&nbsp;&nbsp;&nbsp; UTF16* target = *targetStart;<br>&nbsp;&nbsp;&nbsp; while (source &lt; sourceEnd) {<br>&nbsp;&nbsp;&nbsp; UTF32 ch;<br>&nbsp;&nbsp;&nbsp; if (target &gt;= targetEnd) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = targetExhausted; break;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; ch = *source++;<br>&nbsp;&nbsp;&nbsp; if (ch &lt;= UNI_MAX_BMP) { /**//* Target is a character &lt;= 0xFFFF */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ch &gt;= UNI_SUR_HIGH_START &amp;&amp; ch &lt;= UNI_SUR_LOW_END) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (flags == strictConversion) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --source; /**//* return to the illegal value itself */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceIllegal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *target++ = UNI_REPLACEMENT_CHAR;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *target++ = (UTF16)ch; /**//* normal case */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; } else if (ch &gt; UNI_MAX_LEGAL_UTF32) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (flags == strictConversion) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceIllegal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *target++ = UNI_REPLACEMENT_CHAR;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//* target is a character in range 0xFFFF - 0x10FFFF. */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (target + 1 &gt;= targetEnd) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --source; /**//* Back up source pointer! */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = targetExhausted; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ch -= halfBase;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *target++ = (UTF16)((ch &gt;&gt; halfShift) + UNI_SUR_HIGH_START);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *target++ = (UTF16)((ch &amp; halfMask) + UNI_SUR_LOW_START);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; *sourceStart = source;<br>&nbsp;&nbsp;&nbsp; *targetStart = target;<br>&nbsp;&nbsp;&nbsp; return result;<br>}</p>
<p>/**//* --------------------------------------------------------------------- */</p>
<p>ConversionResult ConvertUTF16toUTF32 (<br>&nbsp;&nbsp;&nbsp; const UTF16** sourceStart, const UTF16* sourceEnd, <br>&nbsp;&nbsp;&nbsp; UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {<br>&nbsp;&nbsp;&nbsp; ConversionResult result = conversionOK;<br>&nbsp;&nbsp;&nbsp; const UTF16* source = *sourceStart;<br>&nbsp;&nbsp;&nbsp; UTF32* target = *targetStart;<br>&nbsp;&nbsp;&nbsp; UTF32 ch, ch2;<br>&nbsp;&nbsp;&nbsp; while (source &lt; sourceEnd) {<br>&nbsp;&nbsp;&nbsp; const UTF16* oldSource = source; /**//*&nbsp; In case we have to back up because of target overflow. */<br>&nbsp;&nbsp;&nbsp; ch = *source++;<br>&nbsp;&nbsp;&nbsp; /**//* If we have a surrogate pair, convert to UTF32 first. */<br>&nbsp;&nbsp;&nbsp; if (ch &gt;= UNI_SUR_HIGH_START &amp;&amp; ch &lt;= UNI_SUR_HIGH_END) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//* If the 16 bits following the high surrogate are in the source buffer */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (source &lt; sourceEnd) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ch2 = *source;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//* If it's a low surrogate, convert to UTF32. */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ch2 &gt;= UNI_SUR_LOW_START &amp;&amp; ch2 &lt;= UNI_SUR_LOW_END) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ch = ((ch - UNI_SUR_HIGH_START) &lt;&lt; halfShift)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + (ch2 - UNI_SUR_LOW_START) + halfBase;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++source;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (flags == strictConversion) { /**//* it's an unpaired high surrogate */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --source; /**//* return to the illegal value itself */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceIllegal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else { /**//* We don't have the 16 bits following the high surrogate. */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --source; /**//* return to the high surrogate */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceExhausted;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; } else if (flags == strictConversion) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//* UTF-16 surrogate values are illegal in UTF-32 */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ch &gt;= UNI_SUR_LOW_START &amp;&amp; ch &lt;= UNI_SUR_LOW_END) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --source; /**//* return to the illegal value itself */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceIllegal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; if (target &gt;= targetEnd) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; source = oldSource; /**//* Back up source pointer! */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = targetExhausted; break;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; *target++ = ch;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; *sourceStart = source;<br>&nbsp;&nbsp;&nbsp; *targetStart = target;<br>#ifdef CVTUTF_DEBUG<br>if (result == sourceIllegal) {<br>&nbsp;&nbsp;&nbsp; fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);<br>&nbsp;&nbsp;&nbsp; fflush(stderr);<br>}<br>#endif<br>&nbsp;&nbsp;&nbsp; return result;<br>}</p>
<p>/**//* --------------------------------------------------------------------- */</p>
<p>/**//*<br>&nbsp;* Index into the table below with the first byte of a UTF-8 sequence to<br>&nbsp;* get the number of trailing bytes that are supposed to follow it.<br>&nbsp;* Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is<br>&nbsp;* left as-is for anyone who may want to do such conversion, which was<br>&nbsp;* allowed in earlier algorithms.<br>&nbsp;*/<br>static const char trailingBytesForUTF8[256] = {<br>&nbsp;&nbsp;&nbsp; 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,<br>&nbsp;&nbsp;&nbsp; 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,<br>&nbsp;&nbsp;&nbsp; 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,<br>&nbsp;&nbsp;&nbsp; 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,<br>&nbsp;&nbsp;&nbsp; 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,<br>&nbsp;&nbsp;&nbsp; 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,<br>&nbsp;&nbsp;&nbsp; 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,<br>&nbsp;&nbsp;&nbsp; 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5<br>};</p>
<p>/**//*<br>&nbsp;* Magic values subtracted from a buffer value during UTF8 conversion.<br>&nbsp;* This table contains as many values as there might be trailing bytes<br>&nbsp;* in a UTF-8 sequence.<br>&nbsp;*/<br>static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x03C82080UL, 0xFA082080UL, 0x82082080UL };</p>
<p>/**//*<br>&nbsp;* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed<br>&nbsp;* into the first byte, depending on how many bytes follow.&nbsp; There are<br>&nbsp;* as many entries in this table as there are UTF-8 sequence types.<br>&nbsp;* (I.e., one byte sequence, two byte etc.). Remember that sequencs<br>&nbsp;* for *legal* UTF-8 will be 4 or fewer bytes total.<br>&nbsp;*/<br>static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };</p>
<p>/**//* --------------------------------------------------------------------- */</p>
<p>/**//* The interface converts a whole buffer to avoid function-call overhead.<br>&nbsp;* Constants have been gathered. Loops &amp; conditionals have been removed as<br>&nbsp;* much as possible for efficiency, in favor of drop-through switches.<br>&nbsp;* (See "Note A" at the bottom of the file for equivalent code.)<br>&nbsp;* If your compiler supports it, the "isLegalUTF8" call can be turned<br>&nbsp;* into an inline function.<br>&nbsp;*/</p>
<p>/**//* --------------------------------------------------------------------- */</p>
<p>ConversionResult ConvertUTF16toUTF8 (<br>&nbsp;&nbsp;&nbsp; const UTF16** sourceStart, const UTF16* sourceEnd, <br>&nbsp;&nbsp;&nbsp; UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {<br>&nbsp;&nbsp;&nbsp; ConversionResult result = conversionOK;<br>&nbsp;&nbsp;&nbsp; const UTF16* source = *sourceStart;<br>&nbsp;&nbsp;&nbsp; UTF8* target = *targetStart;<br>&nbsp;&nbsp;&nbsp; while (source &lt; sourceEnd) {<br>&nbsp;&nbsp;&nbsp; UTF32 ch;<br>&nbsp;&nbsp;&nbsp; unsigned short bytesToWrite = 0;<br>&nbsp;&nbsp;&nbsp; const UTF32 byteMask = 0xBF;<br>&nbsp;&nbsp;&nbsp; const UTF32 byteMark = 0x80; <br>&nbsp;&nbsp;&nbsp; const UTF16* oldSource = source; /**//* In case we have to back up because of target overflow. */<br>&nbsp;&nbsp;&nbsp; ch = *source++;<br>&nbsp;&nbsp;&nbsp; /**//* If we have a surrogate pair, convert to UTF32 first. */<br>&nbsp;&nbsp;&nbsp; if (ch &gt;= UNI_SUR_HIGH_START &amp;&amp; ch &lt;= UNI_SUR_HIGH_END) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//* If the 16 bits following the high surrogate are in the source buffer */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (source &lt; sourceEnd) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UTF32 ch2 = *source;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//* If it's a low surrogate, convert to UTF32. */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ch2 &gt;= UNI_SUR_LOW_START &amp;&amp; ch2 &lt;= UNI_SUR_LOW_END) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ch = ((ch - UNI_SUR_HIGH_START) &lt;&lt; halfShift)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + (ch2 - UNI_SUR_LOW_START) + halfBase;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++source;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (flags == strictConversion) { /**//* it's an unpaired high surrogate */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --source; /**//* return to the illegal value itself */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceIllegal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else { /**//* We don't have the 16 bits following the high surrogate. */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --source; /**//* return to the high surrogate */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceExhausted;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; } else if (flags == strictConversion) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//* UTF-16 surrogate values are illegal in UTF-32 */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ch &gt;= UNI_SUR_LOW_START &amp;&amp; ch &lt;= UNI_SUR_LOW_END) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --source; /**//* return to the illegal value itself */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceIllegal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; /**//* Figure out how many bytes the result will require */<br>&nbsp;&nbsp;&nbsp; if (ch &lt; (UTF32)0x80) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bytesToWrite = 1;<br>&nbsp;&nbsp;&nbsp; } else if (ch &lt; (UTF32)0x800) {&nbsp;&nbsp;&nbsp;&nbsp; bytesToWrite = 2;<br>&nbsp;&nbsp;&nbsp; } else if (ch &lt; (UTF32)0x10000) {&nbsp;&nbsp; bytesToWrite = 3;<br>&nbsp;&nbsp;&nbsp; } else if (ch &lt; (UTF32)0x110000) {&nbsp; bytesToWrite = 4;<br>&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bytesToWrite = 3;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ch = UNI_REPLACEMENT_CHAR;<br>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; target += bytesToWrite;<br>&nbsp;&nbsp;&nbsp; if (target &gt; targetEnd) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; source = oldSource; /**//* Back up source pointer! */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; target -= bytesToWrite; result = targetExhausted; break;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; switch (bytesToWrite) { /**//* note: everything falls through. */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 4: *--target = (UTF8)((ch | byteMark) &amp; byteMask); ch &gt;&gt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 3: *--target = (UTF8)((ch | byteMark) &amp; byteMask); ch &gt;&gt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 2: *--target = (UTF8)((ch | byteMark) &amp; byteMask); ch &gt;&gt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 1: *--target =&nbsp; (UTF8)(ch | firstByteMark[bytesToWrite]);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; target += bytesToWrite;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; *sourceStart = source;<br>&nbsp;&nbsp;&nbsp; *targetStart = target;<br>&nbsp;&nbsp;&nbsp; return result;<br>}</p>
<p>/**//* --------------------------------------------------------------------- */</p>
<p>/**//*<br>&nbsp;* Utility routine to tell whether a sequence of bytes is legal UTF-8.<br>&nbsp;* This must be called with the length pre-determined by the first byte.<br>&nbsp;* If not calling this from ConvertUTF8to*, then the length can be set by:<br>&nbsp;*&nbsp; length = trailingBytesForUTF8[*source]+1;<br>&nbsp;* and the sequence is illegal right away if there aren't that many bytes<br>&nbsp;* available.<br>&nbsp;* If presented with a length &gt; 4, this returns false.&nbsp; The Unicode<br>&nbsp;* definition of UTF-8 goes up to 4-byte sequences.<br>&nbsp;*/</p>
<p>static Boolean isLegalUTF8(const UTF8 *source, int length) {<br>&nbsp;&nbsp;&nbsp; UTF8 a;<br>&nbsp;&nbsp;&nbsp; const UTF8 *srcptr = source+length;<br>&nbsp;&nbsp;&nbsp; switch (length) {<br>&nbsp;&nbsp;&nbsp; default: return false;<br>&nbsp;&nbsp;&nbsp; /**//* Everything else falls through when "true" */<br>&nbsp;&nbsp;&nbsp; case 4: if ((a = (*--srcptr)) &lt; 0x80 || a &gt; 0xBF) return false;<br>&nbsp;&nbsp;&nbsp; case 3: if ((a = (*--srcptr)) &lt; 0x80 || a &gt; 0xBF) return false;<br>&nbsp;&nbsp;&nbsp; case 2: if ((a = (*--srcptr)) &gt; 0xBF) return false;</p>
<p>&nbsp;&nbsp;&nbsp; switch (*source) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//* no fall-through in this inner switch */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 0xE0: if (a &lt; 0xA0) return false; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 0xED: if (a &gt; 0x9F) return false; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 0xF0: if (a &lt; 0x90) return false; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 0xF4: if (a &gt; 0x8F) return false; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default:&nbsp;&nbsp; if (a &lt; 0x80) return false;<br>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; case 1: if (*source &gt;= 0x80 &amp;&amp; *source &lt; 0xC2) return false;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; if (*source &gt; 0xF4) return false;<br>&nbsp;&nbsp;&nbsp; return true;<br>}</p>
<p>/**//* --------------------------------------------------------------------- */</p>
<p>/**//*<br>&nbsp;* Exported function to return whether a UTF-8 sequence is legal or not.<br>&nbsp;* This is not used here; it's just exported.<br>&nbsp;*/<br>Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {<br>&nbsp;&nbsp;&nbsp; int length = trailingBytesForUTF8[*source]+1;<br>&nbsp;&nbsp;&nbsp; if (source+length &gt; sourceEnd) {<br>&nbsp;&nbsp;&nbsp; return false;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return isLegalUTF8(source, length);<br>}</p>
<p>/**//* --------------------------------------------------------------------- */</p>
<p>ConversionResult ConvertUTF8toUTF16 (<br>&nbsp;&nbsp;&nbsp; const UTF8** sourceStart, const UTF8* sourceEnd, <br>&nbsp;&nbsp;&nbsp; UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {<br>&nbsp;&nbsp;&nbsp; ConversionResult result = conversionOK;<br>&nbsp;&nbsp;&nbsp; const UTF8* source = *sourceStart;<br>&nbsp;&nbsp;&nbsp; UTF16* target = *targetStart;<br>&nbsp;&nbsp;&nbsp; while (source &lt; sourceEnd) {<br>&nbsp;&nbsp;&nbsp; UTF32 ch = 0;<br>&nbsp;&nbsp;&nbsp; unsigned short extraBytesToRead = trailingBytesForUTF8[*source];<br>&nbsp;&nbsp;&nbsp; if (source + extraBytesToRead &gt;= sourceEnd) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceExhausted; break;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; /**//* Do this check whether lenient or strict */<br>&nbsp;&nbsp;&nbsp; if (! isLegalUTF8(source, extraBytesToRead+1)) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceIllegal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; /**//*<br>&nbsp;&nbsp;&nbsp;&nbsp; * The cases all fall through. See "Note A" below.<br>&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp; switch (extraBytesToRead) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 5: ch += *source++; ch &lt;&lt;= 6; /**//* remember, illegal UTF-8 */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 4: ch += *source++; ch &lt;&lt;= 6; /**//* remember, illegal UTF-8 */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 3: ch += *source++; ch &lt;&lt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 2: ch += *source++; ch &lt;&lt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 1: ch += *source++; ch &lt;&lt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 0: ch += *source++;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; ch -= offsetsFromUTF8[extraBytesToRead];</p>
<p>&nbsp;&nbsp;&nbsp; if (target &gt;= targetEnd) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; source -= (extraBytesToRead+1); /**//* Back up source pointer! */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = targetExhausted; break;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; if (ch &lt;= UNI_MAX_BMP) { /**//* Target is a character &lt;= 0xFFFF */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//* UTF-16 surrogate values are illegal in UTF-32 */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ch &gt;= UNI_SUR_HIGH_START &amp;&amp; ch &lt;= UNI_SUR_LOW_END) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (flags == strictConversion) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; source -= (extraBytesToRead+1); /**//* return to the illegal value itself */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceIllegal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *target++ = UNI_REPLACEMENT_CHAR;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *target++ = (UTF16)ch; /**//* normal case */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; } else if (ch &gt; UNI_MAX_UTF16) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (flags == strictConversion) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceIllegal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; source -= (extraBytesToRead+1); /**//* return to the start */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break; /**//* Bail out; shouldn't continue */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *target++ = UNI_REPLACEMENT_CHAR;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//* target is a character in range 0xFFFF - 0x10FFFF. */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (target + 1 &gt;= targetEnd) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; source -= (extraBytesToRead+1); /**//* Back up source pointer! */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = targetExhausted; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ch -= halfBase;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *target++ = (UTF16)((ch &gt;&gt; halfShift) + UNI_SUR_HIGH_START);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *target++ = (UTF16)((ch &amp; halfMask) + UNI_SUR_LOW_START);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; *sourceStart = source;<br>&nbsp;&nbsp;&nbsp; *targetStart = target;<br>&nbsp;&nbsp;&nbsp; return result;<br>}</p>
<p>/**//* --------------------------------------------------------------------- */</p>
<p>ConversionResult ConvertUTF32toUTF8 (<br>&nbsp;&nbsp;&nbsp; const UTF32** sourceStart, const UTF32* sourceEnd, <br>&nbsp;&nbsp;&nbsp; UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {<br>&nbsp;&nbsp;&nbsp; ConversionResult result = conversionOK;<br>&nbsp;&nbsp;&nbsp; const UTF32* source = *sourceStart;<br>&nbsp;&nbsp;&nbsp; UTF8* target = *targetStart;<br>&nbsp;&nbsp;&nbsp; while (source &lt; sourceEnd) {<br>&nbsp;&nbsp;&nbsp; UTF32 ch;<br>&nbsp;&nbsp;&nbsp; unsigned short bytesToWrite = 0;<br>&nbsp;&nbsp;&nbsp; const UTF32 byteMask = 0xBF;<br>&nbsp;&nbsp;&nbsp; const UTF32 byteMark = 0x80; <br>&nbsp;&nbsp;&nbsp; ch = *source++;<br>&nbsp;&nbsp;&nbsp; if (flags == strictConversion ) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//* UTF-16 surrogate values are illegal in UTF-32 */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ch &gt;= UNI_SUR_HIGH_START &amp;&amp; ch &lt;= UNI_SUR_LOW_END) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --source; /**//* return to the illegal value itself */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceIllegal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; /**//*<br>&nbsp;&nbsp;&nbsp;&nbsp; * Figure out how many bytes the result will require. Turn any<br>&nbsp;&nbsp;&nbsp;&nbsp; * illegally large UTF32 things (&gt; Plane 17) into replacement chars.<br>&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp; if (ch &lt; (UTF32)0x80) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bytesToWrite = 1;<br>&nbsp;&nbsp;&nbsp; } else if (ch &lt; (UTF32)0x800) {&nbsp;&nbsp;&nbsp;&nbsp; bytesToWrite = 2;<br>&nbsp;&nbsp;&nbsp; } else if (ch &lt; (UTF32)0x10000) {&nbsp;&nbsp; bytesToWrite = 3;<br>&nbsp;&nbsp;&nbsp; } else if (ch &lt;= UNI_MAX_LEGAL_UTF32) {&nbsp; bytesToWrite = 4;<br>&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bytesToWrite = 3;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ch = UNI_REPLACEMENT_CHAR;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceIllegal;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; target += bytesToWrite;<br>&nbsp;&nbsp;&nbsp; if (target &gt; targetEnd) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --source; /**//* Back up source pointer! */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; target -= bytesToWrite; result = targetExhausted; break;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; switch (bytesToWrite) { /**//* note: everything falls through. */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 4: *--target = (UTF8)((ch | byteMark) &amp; byteMask); ch &gt;&gt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 3: *--target = (UTF8)((ch | byteMark) &amp; byteMask); ch &gt;&gt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 2: *--target = (UTF8)((ch | byteMark) &amp; byteMask); ch &gt;&gt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; target += bytesToWrite;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; *sourceStart = source;<br>&nbsp;&nbsp;&nbsp; *targetStart = target;<br>&nbsp;&nbsp;&nbsp; return result;<br>}</p>
<p>/**//* --------------------------------------------------------------------- */</p>
<p>ConversionResult ConvertUTF8toUTF32 (<br>&nbsp;&nbsp;&nbsp; const UTF8** sourceStart, const UTF8* sourceEnd, <br>&nbsp;&nbsp;&nbsp; UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {<br>&nbsp;&nbsp;&nbsp; ConversionResult result = conversionOK;<br>&nbsp;&nbsp;&nbsp; const UTF8* source = *sourceStart;<br>&nbsp;&nbsp;&nbsp; UTF32* target = *targetStart;<br>&nbsp;&nbsp;&nbsp; while (source &lt; sourceEnd) {<br>&nbsp;&nbsp;&nbsp; UTF32 ch = 0;<br>&nbsp;&nbsp;&nbsp; unsigned short extraBytesToRead = trailingBytesForUTF8[*source];<br>&nbsp;&nbsp;&nbsp; if (source + extraBytesToRead &gt;= sourceEnd) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceExhausted; break;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; /**//* Do this check whether lenient or strict */<br>&nbsp;&nbsp;&nbsp; if (! isLegalUTF8(source, extraBytesToRead+1)) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceIllegal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; /**//*<br>&nbsp;&nbsp;&nbsp;&nbsp; * The cases all fall through. See "Note A" below.<br>&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp; switch (extraBytesToRead) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 5: ch += *source++; ch &lt;&lt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 4: ch += *source++; ch &lt;&lt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 3: ch += *source++; ch &lt;&lt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 2: ch += *source++; ch &lt;&lt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 1: ch += *source++; ch &lt;&lt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 0: ch += *source++;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; ch -= offsetsFromUTF8[extraBytesToRead];</p>
<p>&nbsp;&nbsp;&nbsp; if (target &gt;= targetEnd) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; source -= (extraBytesToRead+1); /**//* Back up the source pointer! */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = targetExhausted; break;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; if (ch &lt;= UNI_MAX_LEGAL_UTF32) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//*<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * UTF-16 surrogate values are illegal in UTF-32, and anything<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * over Plane 17 (&gt; 0x10FFFF) is illegal.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ch &gt;= UNI_SUR_HIGH_START &amp;&amp; ch &lt;= UNI_SUR_LOW_END) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (flags == strictConversion) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; source -= (extraBytesToRead+1); /**//* return to the illegal value itself */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceIllegal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *target++ = UNI_REPLACEMENT_CHAR;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *target++ = ch;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; } else { /**//* i.e., ch &gt; UNI_MAX_LEGAL_UTF32 */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = sourceIllegal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *target++ = UNI_REPLACEMENT_CHAR;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; *sourceStart = source;<br>&nbsp;&nbsp;&nbsp; *targetStart = target;<br>&nbsp;&nbsp;&nbsp; return result;<br>}</p>
<p>/**//* ---------------------------------------------------------------------</p>
<p>&nbsp;&nbsp;&nbsp; Note A.<br>&nbsp;&nbsp;&nbsp; The fall-through switches in UTF-8 reading code save a<br>&nbsp;&nbsp;&nbsp; temp variable, some decrements &amp; conditionals.&nbsp; The switches<br>&nbsp;&nbsp;&nbsp; are equivalent to the following loop:<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int tmpBytesToRead = extraBytesToRead+1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ch += *source++;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --tmpBytesToRead;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (tmpBytesToRead) ch &lt;&lt;= 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } while (tmpBytesToRead &gt; 0);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; In UTF-8 writing code, the switches on "bytesToWrite" are<br>&nbsp;&nbsp;&nbsp; similarly unrolled loops.</p>
<p>&nbsp;&nbsp; --------------------------------------------------------------------- */</p>
<p>&nbsp;</p>
<p>三 C++ 的字符串与C#的转化</p>
<p>1）将system::String 转化为C++的string：<br>// convert_system_string.cpp<br>// compile with: /clr<br>#include &lt;string&gt;<br>#include &lt;iostream&gt;<br>using namespace std;<br>using namespace System;</p>
<p>void MarshalString ( String ^ s, string&amp; os ) {<br>&nbsp;&nbsp; using namespace Runtime::InteropServices;<br>&nbsp;&nbsp; const char* chars = <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();<br>&nbsp;&nbsp; os = chars;<br>&nbsp;&nbsp; Marshal::FreeHGlobal(IntPtr((void*)chars));<br>}</p>
<p>void MarshalString ( String ^ s, wstring&amp; os ) {<br>&nbsp;&nbsp; using namespace Runtime::InteropServices;<br>&nbsp;&nbsp; const wchar_t* chars = <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (const wchar_t*)(Marshal::StringToHGlobalUni(s)).ToPointer();<br>&nbsp;&nbsp; os = chars;<br>&nbsp;&nbsp; Marshal::FreeHGlobal(IntPtr((void*)chars));<br>}</p>
<p>int main() {<br>&nbsp;&nbsp; string a = "test";<br>&nbsp;&nbsp; wstring b = L"test2";<br>&nbsp;&nbsp; String ^ c = gcnew String("abcd");</p>
<p>&nbsp;&nbsp; cout &lt;&lt; a &lt;&lt; endl;<br>&nbsp;&nbsp; MarshalString(c, a);<br>&nbsp;&nbsp; c = "efgh";<br>&nbsp;&nbsp; MarshalString(c, b);<br>&nbsp;&nbsp; cout &lt;&lt; a &lt;&lt; endl;<br>&nbsp;&nbsp; wcout &lt;&lt; b &lt;&lt; endl;<br>}</p>
<p><br>2）将System::String转化为char*或w_char*<br>// convert_string_to_wchar.cpp<br>// compile with: /clr<br>#include &lt; stdio.h &gt;<br>#include &lt; stdlib.h &gt;<br>#include &lt; vcclr.h &gt;</p>
<p>using namespace System;</p>
<p>int main() {<br>&nbsp;&nbsp; String ^str = "Hello";</p>
<p>&nbsp;&nbsp; // Pin memory so GC can't move it while native function is called<br>&nbsp;&nbsp; pin_ptr&lt;const wchar_t&gt; wch = PtrToStringChars(str);<br>&nbsp;&nbsp; printf_s("%S\n", wch);</p>
<p>&nbsp;&nbsp; // Conversion to char* :<br>&nbsp;&nbsp; // Can just convert wchar_t* to char* using one of the <br>&nbsp;&nbsp; // conversion functions such as: <br>&nbsp;&nbsp; // WideCharToMultiByte()<br>&nbsp;&nbsp; // wcstombs_s()<br>&nbsp;&nbsp; //&nbsp; etc<br>&nbsp;&nbsp; size_t convertedChars = 0;<br>&nbsp;&nbsp; size_t&nbsp; sizeInBytes = ((str-&gt;Length + 1) * 2);<br>&nbsp;&nbsp; errno_t err = 0;<br>&nbsp;&nbsp; char&nbsp;&nbsp;&nbsp; *ch = (char *)malloc(sizeInBytes);</p>
<p>&nbsp;&nbsp; err = wcstombs_s(&amp;convertedChars, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ch, sizeInBytes,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wch, sizeInBytes);<br>&nbsp;&nbsp; if (err != 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf_s("wcstombs_s&nbsp; failed!\n");</p>
<p>&nbsp;&nbsp;&nbsp; printf_s("%s\n", ch);<br>}</p>
<p><br>&nbsp;</p>
<img src ="http://www.cppblog.com/megax/aggbug/58279.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/megax/" target="_blank">megax</a> 2008-08-07 20:18 <a href="http://www.cppblog.com/megax/articles/58279.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]vi常用操作</title><link>http://www.cppblog.com/megax/articles/44182.html</link><dc:creator>megax</dc:creator><author>megax</author><pubDate>Tue, 11 Mar 2008 06:14:00 GMT</pubDate><guid>http://www.cppblog.com/megax/articles/44182.html</guid><wfw:comment>http://www.cppblog.com/megax/comments/44182.html</wfw:comment><comments>http://www.cppblog.com/megax/articles/44182.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/megax/comments/commentRss/44182.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/megax/services/trackbacks/44182.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1)文件操作&nbsp;&nbsp; vi FileName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打开文件 Fi...&nbsp;&nbsp;<a href='http://www.cppblog.com/megax/articles/44182.html'>阅读全文</a><img src ="http://www.cppblog.com/megax/aggbug/44182.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/megax/" target="_blank">megax</a> 2008-03-11 14:14 <a href="http://www.cppblog.com/megax/articles/44182.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Linux常见问题解答</title><link>http://www.cppblog.com/megax/articles/44181.html</link><dc:creator>megax</dc:creator><author>megax</author><pubDate>Tue, 11 Mar 2008 06:12:00 GMT</pubDate><guid>http://www.cppblog.com/megax/articles/44181.html</guid><wfw:comment>http://www.cppblog.com/megax/comments/44181.html</wfw:comment><comments>http://www.cppblog.com/megax/articles/44181.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/megax/comments/commentRss/44181.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/megax/services/trackbacks/44181.html</trackback:ping><description><![CDATA[<p>一、 如何建立多用户<br>　　adduser newuser接着输入命令passwd newuser，屏幕将提示输入口令，再次输入确认， 一个新的用户就增加成功<br>　　Linux提供了六个虚拟控制台，用ALT+F1~F6切换（在X-window下用CRTL+ALT+F1~F6切换），每个控制台均可以用不同的用户登录，运行不同的程序。</p>
<p><a id=more-43></a></p>
<p>二、在Linux下如何使用软盘、光盘以及DOS等非Linux分区</p>
<p>　　装载的命令是mount，格式如下：mount -t 文件系统类型 设备名 装载目录</p>
<p>　　文件系统类型就是分区格式，Linux支持的文件系统类型有许多：</p>
<p>　　msdos DOS分区文件系统类型<br>　　vfat 支持长文件名的DOS分区文件（可以理解为Windows文件）系统类型<br>　　iso9660 光盘的文件系统类型<br>　　ext2 Linux的文件系统类型</p>
<p>　　设备名，指的是你要装载的设备的名称。软盘一般为/dev/fd0 fd1；光盘则根据你的光驱的位置来决定，通常光驱装在第二硬盘的主盘位置就是/dev/hdc;如果访问的是DOS的分区，则列出其设备名，如/dev/hda1是指第一硬盘的第一个分区。 装载目录，就是你指定设备的载入点。</p>
<p>　　1. 装载软盘</p>
<p>　　首先用mkdir /mnt/floppy 在/mnt目录下建立一个空的floppy目录，然后输入mount -t msdos /dev/fd0 /mnt/floppy 将DOS文件格式的一张软盘装载进来，以后就可以在/mnt/floppy目录下找到这张软盘的所有内容。</p>
<p>　　2. 装载Windows所在的C盘</p>
<p>　　mkdir /mnt/c 在/mnt目录下建立一个空的c目录;<br>　　mount -t vfat /dev/hda1 /mnt/c 将Windows的C盘按长文件名格式装载到/mnt/c目录下，以后在该目录下就能读写C盘根目录中的内容。</p>
<p>　　3.装载光盘</p>
<p>　　mkdir /mnt/cdrom 在/mnt目录下建立一个空的cdrom目录;<br>　　mount -t iso9660 /dev/hdc /mnt/cdrom 将光盘载入到文件系统中来，将在/mnt/cdrom目录下找到光盘内容。有的Linux版本允许用mount /dev/cdrom或mount /mnt/cdrom命令装载光盘。<br>　　要注意的是，用mount命令装入的是软盘、光盘，而不是软驱、光驱。有些初学者容易犯一个毛病，以为用上面命令后，软驱就成了/mnt/floppy，光驱就成了/mnt/cdrom，其实不然，当你要换一张光盘或软盘时，一定要先卸载，再对新盘重新装载。</p>
<p>　　4.卸载</p>
<p>　　卸载的命令格式是:umonut 目录名，例如要卸载软盘，可输入命令umonut /mnt/floppy。要注意的是，在卸载光盘之前，直接按光驱面板上的弹出键是不会起作用的。</p>
<p>三、RPM的使用方法</p>
<p>1. 用RPM安装软件包 ：rpm -ivh 软件文件名<br>　　例如 rpm -ivh fvwm95-2.0.43a.chinese-1.i386.rpm 屏幕上就会输出该软件包的名称和安装的进度条:<br>　　fvwm95 ###############<br>　　当进度条走到底，中文fvwm95（一种X-Window的界面）就安装完了，再运行X-Window，啊，全中文的fvwm95就在我的眼前。</p>
<p>2. 用RPM反安装软件包:rpm -e 软件名<br>　　例如:rpm -e fvwm95</p>
<p>3. 用RPM升级软件包:rpm -Uvh 软件升级版文件名<br>　　例如:rpm -Uvh fvwm95-2.1.0a.chinese-1.i386.rpm，RPM自动反安装原来的老版本，将升级版的软件安装入系统。</p>
<p>四、Linux开机直接进入文本界面，怎样才能让它默认进入图形界面？</p>
<p>修改/etc/inittab文件，其中有一行id:3:initdefault，意思是说开机默认进入运行级别3（多用户的文本界面），把它改成id:5:initdefault，既开机默认进入运行级别5（多用户的图形界面）。这样就行了。</p>
<p>五、如何将man转存为文本文件？</p>
<p>以ls的man为例<br>man ls |col -b &gt;ls.txt<br>将info变成文本,以make为例<br>info make -o make.txt -s</p>
<p>六、如何将将 man page 转成 HTML 格式？</p>
<p>使用 man2html 这个指令，就可以将 man page 转成 HTML 格式了。用法是：</p>
<p>man2html filename &gt; htmlfile.html</p>
<p>七、.tar，.tar.gz，.bz2，.tar.bz2，.bz，.gz是什么文件，如何解开他们？<br>他们都是文件(压缩)包。<br>.tar：把文件打包，不压缩：tar cvf *.tar dirName 解开：tar xvf *.tar<br>.tar.gz：把文件打包并压缩：tar czvf *.tar.gz dirName 解开：tar xzvf *.tar.gz<br>.bz2：解开：bzip2 -d *.bz2<br>.bz：解开：bzip -d *.bz<br>.gz：解开：gzip -d *.gz</p>
<p>八、linux下如何解开.zip，.rar压缩文件？<br>rh8下有一个图形界面的软件file-roller可以做这件事。令外可以用unzip *.zip解开zip文件，unrar *.rar解开rar文件，不过unrar一般系统不自带，要到网上下载。</p>
<p>九、linux下如何浏览.iso光盘镜像文件？<br>a.建一个目录，如：mkdir a<br>b.把iso文件挂载到该目录上：mount -o loop xxxx.iso a<br>现在目录a里的内容就是iso文件里的内容了。</p>
<p>十、linux下如何配置网络？<br>用netconfig。&#8220;IP address:&#8221;就是要配置的IP地址，&#8220;Netmask:&#8221;子网掩码，&#8220;Default gateway (IP):&#8221;网关，&#8220;Primary nameserver:&#8221;DNS服务器IP</p>
<p>十一、如何让linux启动后自动挂载制定分区？<br>编辑/etc/fstab文件，在里面加入相应的行</p>
<p>十二、如何定制linux启动时启动的服务？<br>在控制台或终端下运行ntsysv，然后把要启动的服务选上，如果要开机不启动某个那就把他的选中去掉。</p>
<p>十三、删除文件大小为零的文件<br>rm -i `find ./ -size 0`<br>find ./ -size 0 -exec rm {} \;<br>find ./ -size |xargs rm -f &amp;非常有效<br>for file in * #自己定义需要删除的文件类型<br>do<br>if [ ! -s ${file} ]<br>then<br>rm ${file}<br>echo &#8220;rm $file Success!&#8221;<br>fi<br>done</p>
<p>十四、查看系统信息<br>cat /proc/cpuinfo - CPU (i.e. vendor, Mhz, flags like mmx)<br>cat /proc/interrupts - 中断<br>cat /proc/ioports - 设备IO端口<br>cat /proc/meminfo - 内存信息(i.e. mem used, free, swap size)<br>cat /proc/partitions - 所有设备的所有分区<br>cat /proc/pci - PCI设备的信息<br>cat /proc/swaps - 所有Swap分区的信息<br>cat /proc/version - Linux的版本号 相当于 uname -r<br>uname -a - 看系统内核等信息</p>
<p>十五、cd光盘做成iso文件<br>cp /dev/cdrom xxxx.iso</p>
<p>十六、快速观看开机的硬件检测<br>dmesg | more</p>
<p>十七、查看硬盘的使用情况<br>df -k 以K为单位显示<br>df -h 以人性化单位显示，可以是b,k,m,g,t..</p>
<p>十八、查看目录的大小<br>du -sh dirname<br>-s 仅显示总计<br>-h 以K、M、G为单位，提高信息的可读性。KB、MB、GB是以1024为换算单位，-H以1000为换算单位。</p>
<p>十九、查找或删除正在使用某文件的进程<br>fuser filename<br>fuser -k filename</p>
<p>二十、字符模式下设置/删除环境变量<br>bash下<br>设置：export 变量名=变量值<br>删除：unset 变量名<br>csh下<br>设置：setenv 变量名 变量值<br>删除：unsetenv 变量名</p>
<p>二十一、vim中显示颜色或不显示颜色<br>vi ~/.vimrc; 如果有syntax on，则显示颜色，syntax off，则不显示颜色</p>
<p>二十二、修改系统时间<br>date -s &#8220;2003-04-14 cst&#8221;，cst指时区，时间设定用date -s 18:10</p>
<p>二十三、开机就mount上windows下的分区<br>自动将windows的d盘挂到/mnt/d上，用vi打开/etc/fstab，加入以下一行<br>/dev/hda5 /mnt/d vfat defaults,codepage=936,iocharset=cp936 0 0<br>注意，先得手工建立一个/mnt/d目录</p>
<p>二十四、在多级目录中查找某个文件的方法<br>find /dir -name filename.ext<br>du -a | grep filename.ext<br>locate filename.ext</p>
<p>二十五、不让普通用户自己改密码<br>[root@xin_fc etc]# chmod 511 /usr/bin/passwd<br>又想让普通用户自己改密码<br>[root@xin_fc etc]# chmod 4511 /usr/bin/passwd</p>
<p>二十六、用dd做iso<br>dd if=/dev/cdrom of=/tmp/aaa.iso</p>
<p>二十七、让Linux自动同步时间<br>vi /etc/crontab<br>加上一句<br>00 0 1 * * root rdate -s time.nist.gov</p>
<p>二十八、ssh上来能不能不自动断线<br>那是timetou的设置，修改TMOUT变量值</p>
<p>二十九、监视所有通过本机网卡的数据<br>tcpdump iptraf </p>
<img src ="http://www.cppblog.com/megax/aggbug/44181.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/megax/" target="_blank">megax</a> 2008-03-11 14:12 <a href="http://www.cppblog.com/megax/articles/44181.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]WSAD 小技巧</title><link>http://www.cppblog.com/megax/articles/44179.html</link><dc:creator>megax</dc:creator><author>megax</author><pubDate>Tue, 11 Mar 2008 06:10:00 GMT</pubDate><guid>http://www.cppblog.com/megax/articles/44179.html</guid><wfw:comment>http://www.cppblog.com/megax/comments/44179.html</wfw:comment><comments>http://www.cppblog.com/megax/articles/44179.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/megax/comments/commentRss/44179.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/megax/services/trackbacks/44179.html</trackback:ping><description><![CDATA[<p><span class=tpc_content><font size=2><font color=#00008b><strong>○ 如何更改 WSAD 的界面语种</strong></font></p>
<p>更改 WSAD 安装目录下 wsappdev.ini 在行 VMArgs=-Xj9 后加入，为空则与操作系统默认语言相同。<br>VMArgs=-Xj9 -Duser.language=en -Duser.region=US</p>
<p>其他语言参数：<br>-Duser.language=en -Duser.region=US 【英文】<br>-Duser.language=zh -Duser.region=CN 【中文简体】<br>-Duser.language=zh -Duser.region=TW 【中文繁体】<br><a id=more-41></a><br></font><font color=#00008b><br><strong><font size=2>○ WebSphere Studio Application Developer 5版本中如何更改默认的工作区</font></strong></font></p>
<p><font size=2>在默认情况下，WebSphere Application Developer 5在启动的时候会弹出一个提示窗口让用户选择 workspace。如果，用户选中了窗口下方的&#8220;将此工作空间用作缺省值并且不再显示此对话框&#8221;，那么下一次客户再运行WSAD的时候将不会弹出提示窗口让用户选择工作区。如果，用户再想更换工作区将无法进行。在 Eclipse 3.1 中，File 菜单下有 Switch Workspace 的选项，但是 WSAD 5 是基于 Eclipse 2.x 的，我尝试了很久都没有找到在选项中更改 workspace 的地方。之后在网上检索，查到这个问题有如下解决方案：<br>方法一：用命令行方式启动并指定所用的工作区</p>
<p>1. 打开命令行窗口，进入wsappdev.exe所在的目录(wsappdev.exe应该在WSAD的安装路径下)</p>
<p>2. 执行命令：wsappdev.exe -data <workdirectory>，其中<workdirectory>是需要使用的工作区目录。假设要指定的工作区路径为C:\ workbentch,那么命令就应该写成：wsappdev.exe -data C:\workbentch</p>
<p>方法二：用命令行方式启动并弹出提示窗口让用户选择工作区</p>
<p>1. 打开命令行窗口，进入wsappdev.exe所在的目录</p>
<p>2. 执行命令：wsappdev.exe -setworkspace</p>
<p>方法三：通过更改配置文件让WSAD启动的时候弹出一个提示窗口让用户选择工作区</p>
<p>1. 用文本编辑器打开wsappdev.ini文件(wsappdev.ini文件和wsappdev.exe文件在相同的路径下),默认情况下可以看到类似如下的内容：</p>
<p>[Settings]</p>
<p>DefaultWorkspace=<my Documents>\IBM\wsappdev51\workspace</p>
<p>ProductName=IBM WebSphere Studio Application Developer</p>
<p>Version=5.1.1</p>
<p>Full=Yes</p>
<p>KeyName=wsappdev510</p>
<p>VMArgs=-Xj9</p>
<p>LUMProductID=1</p>
<p>LUMProductVersion=5.1.1</p>
<p>Website=www.ibm.com/websphere/developer/zones/studio/appdev/</p>
<p>[Environment Variables]</p>
<p>2. 在 [Environment Variables] 的上方添加一行 SetWorkSpace=true ，保存 wsappdev.ini 文件。</p>
<p>3. 关闭 wsappdev.ini 文件，通过菜单或者直接双击 wsappdev.exe 文件再次启动 WSAD 的时候，就会弹出一个提示窗口让用户选择工作区。</p>
<p><font color=#00008b><strong>○在 eclipse 的快捷方式后面加一个 参数:-nl &#8220;zh_US&#8221;,就可以找回英文的界面，加参数：-nl &#8220;zh_CN&#8221; ，就可以用到中文界面 </strong></font></font></span></p>
<img src ="http://www.cppblog.com/megax/aggbug/44179.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/megax/" target="_blank">megax</a> 2008-03-11 14:10 <a href="http://www.cppblog.com/megax/articles/44179.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]AWK说明</title><link>http://www.cppblog.com/megax/articles/44178.html</link><dc:creator>megax</dc:creator><author>megax</author><pubDate>Tue, 11 Mar 2008 06:08:00 GMT</pubDate><guid>http://www.cppblog.com/megax/articles/44178.html</guid><wfw:comment>http://www.cppblog.com/megax/comments/44178.html</wfw:comment><comments>http://www.cppblog.com/megax/articles/44178.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/megax/comments/commentRss/44178.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/megax/services/trackbacks/44178.html</trackback:ping><description><![CDATA[<p>IBM参考文章：<a href="http://www-128.ibm.com/developerworks/cn/linux/shell/awk/awk-1/index.html"><u><font color=#0000ff>http://www-128.ibm.com/developerworks/cn/linux/shell/awk/awk-1/index.html</font></u></a></p>
<p>AWK是一种优良的文本处理工具。它不仅是 Linux 中也是任何环境中现有的功能最强大的数据处理发动机之一。这种编程及数据操作语言（其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母）的最大功能取决于一个人所拥有的知识。 AWK 提供了极其强大的功能：可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。实际上 AWK 的确拥有自己的语言： AWK 程序设计语言，三位创建者已将它正式定义为&#8220;样式扫描和处理语言&#8221;。它允许您创建简短的程序，这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表，还有无数其他的功能。</p>
<p><a id=more-39></a></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 你可能对UNIX比较熟悉，但你可能对awk很陌生，这一点也不奇怪，的确，与其优秀的功能相比，awk还远没达到它应有的知名度。awk是什么？与其它大多数UNIX命令不同的是，从名字上看，我们不可能知道awk的功能：它既不是具有独立意义的英文单词，也不是几个相关单词的缩写。事实上，awk是三个人名的缩写，他们是：Aho、(Peter)Weinberg和 (Brain)Kernighan。正是这三个人创造了awk—一个优秀的样式扫描与处理工具。</p>
<p>　&nbsp; 　最简单地说， AWK 是一种用于处理文本的编程语言工具。AWK 在很多方面类似于 shell 编程语言，尽管 AWK 具有完全属于其本身的语法。它的设计思想来源于 SNOBOL4 、sed 、Marc Rochkind设计的有效性语言、语言工具 yacc 和 lex ，当然还从 C 语言中获取了一些优秀的思想。在最初创造 AWK 时，其目的是用于文本处理，并且这种语言的基础是，只要在输入数据中有模式匹配，就执行一系列指令。该实用工具扫描文件中的每一行，查找与命令行中所给定内容相匹配的模式。如果发现匹配内容，则进行下一个编程步骤。如果找不到匹配内容，则继续处理下一行。</p>
<p>　&nbsp; 　尽管操作可能会很复杂，但命令的语法始终是：</p>
<p>　&nbsp; 　awk &#8216;{pattern + action}&#8217; {filenames}</p>
<p>　&nbsp; 　其中 pattern 表示 AWK 在数据中查找的内容，而 action 是在找到匹配内容时所执行的一系列命令。花括号 ({}) 不需要在程序中始终出现，但它们用于根据特定的模式对一系列指令进行分组。</p>
<p>　&nbsp; 　gawk 是 AWK 的 GNU 版本。</p>
<p>一、AWK的功能是什么？</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 与sed和 grep很相似，awk是一种样式扫描与处理工具。但其功能却大大强于sed和grep。awk提供了极其强大的功能：它几乎可以完成grep和sed所能完成的全部工作，同时，它还可以可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。实际上，awk的确拥有自己的语言：awk程序设计语言，awk的三位创建者已将它正式定义为：样式扫描和处理语言。</p>
<p>二、为什么使用awk?</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 即使如此，你也许仍然会问，我为什么要使用awk?</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用awk的第一个理由是基于文本的样式扫描和处理是我们经常做的工作，awk所做的工作有些象数据库，但与数据库不同的是，它处理的是文本文件，这些文件没有专门的存储格式，普通的人们就能编辑、阅读、理解和处理它们。而数据库文件往往具有特殊的存储格式，这使得它们必须用数据库处理程序来处理它们。既然这种类似于数据库的处理工作我们经常会遇到，我们就应当找到处理它们的简便易行的方法，UNIX有很多这方面的工具，例如sed 、grep、sort以及find等等，awk是其中十分优秀的一种。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用awk的第二个理由是awk是一个简单的工具，当然这是相对于其强大的功能来说的。的确，UNIX有许多优秀的工具，例如UNIX天然的开发工具C语言及其延续C++就非常的优秀。但相对于它们来说，awk完成同样的功能要方便和简捷得多。这首先是因为awk提供了适应多种需要的解决方案：从解决简单问题的awk命令行到复杂而精巧的awk程序设计语言，这样做的好处是，你可以不必用复杂的方法去解决本来很简单的问题。例如，你可以用一个命令行解决简单的问题，而C不行，即使一个再简单的程序，C语言也必须经过编写、编译的全过程。其次，awk本身是解释执行的，这就使得awk程序不必经过编译的过程，同时，这也使得它与shell script程序能够很好的契合。最后，awk本身较C语言简单，虽然awk吸收了C语言很多优秀的成分，熟悉C语言会对学习awk有很大的帮助，但 awk本身不须要会使用C语言——一种功能强大但需要大量时间学习才能掌握其技巧的开发工具。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用awk的第三个理由是awk是一个容易获得的工具。与C和C++语言不同，awk只有一个文件(/bin/awk)，而且几乎每个版本的UNIX都提供各自版本的awk，你完全不必费心去想如何获得awk。但C语言却不是这样，虽然C语言是UNIX天然的开发工具，但这个开发工具却是单独发行的，换言之，你必须为你的UNIX版本的C语言开发工具单独付费（当然使用D版者除外），获得并安装它，然后你才可以使用它。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 基于以上理由，再加上awk强大的功能，我们有理由说，如果你要处理与文本样式扫描相关的工作，awk应该是你的第一选择。在这里有一个可遵循的一般原则：如果你用普通的shell工具或shell script有困难的话，试试awk,如果awk仍不能解决问题，则便用C语言，如果C语言仍然失败，则移至C++。</p>
<p>三、awk的调用方式</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前面曾经说过，awk提供了适应多种需要的不同解决方案，它们是：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、 awk命令行，你可以象使用普通UNIX命令一样使用awk，在命令行中你也可以使用awk程序设计语言，虽然awk支持多行的录入，但是录入长长的命令行并保证其正确无误却是一件令人头疼的事，因此，这种方法一般只用于解决简单的问题。当然，你也可以在shell script程序中引用awk命令行甚至awk程序脚本。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、使用-f选项调用awk程序。awk允许将一段awk程序写入一个文本文件，然后在awk命令行中用-f选项调用并执行这段程序。具体的方法我们将在后面的awk语法中讲到。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3、利用命令解释器调用awk程序：利用UNIX支持的命令解释器功能，我们可以将一段awk程序写入文本文件，然后在它的第一行加上:<br>#!/bin/awk -f<br>并赋予这个文本文件以执行的权限。这样做之后，你就可以在命令行中用类似于下面这样的方式调用并执行这段awk程序了。</p>
<p>$awk脚本文本名 待处理文件</p>
<p>awk的语法：</p>
<p>与其它UNIX命令一样，awk拥有自己的语法：</p>
<p>awk [ -F re] [parameter&#8230;] [&#8217;prog&#8217;] [-f progfile][in_file&#8230;]</p>
<p>参数说明：</p>
<p>-F re:允许awk更改其字段分隔符。</p>
<p>parameter: 该参数帮助为不同的变量赋值。</p>
<p>&#8216;prog&#8217;: awk的程序语句段。这个语句段必须用单拓号：&#8217;和&#8217;括起，以防被shell解释。这个程序语句段的标准形式为：</p>
<p>&#8216;pattern {action}&#8217;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其中pattern参数可以是egrep正则表达式中的任何一个，它可以使用语法/re/再加上一些样式匹配技巧构成。与sed类似，你也可以使用&#8221;,&#8221;分开两样式以选择某个范围。关于匹配的细节，你可以参考附录，如果仍不懂的话，找本UNIX书学学grep和sed（本人是在学习ed时掌握匹配技术的）。 action参数总是被大括号包围，它由一系统awk语句组成，各语句之间用&#8221;;&#8221;分隔。awk解释它们，并在pattern给定的样式匹配的记录上执行其操作。与shell类似，你也可以使用&#8220;#&#8221;作为注释符，它使&#8220;#&#8221;到行尾的内容成为注释，在解释执行时，它们将被忽略。你可以省略pattern和 action之一，但不能两者同时省略，当省略pattern时没有样式匹配，表示对所有行（记录）均执行操作，省略action时执行缺省的操作——在标准输出上显示。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -f progfile:允许awk调用并执行progfile指定有程序文件。progfile是一个文本文件，他必须符合awk的语法。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in_file:awk的输入文件，awk允许对多个输入文件进行处理。值得注意的是awk不修改输入文件。如果未指定输入文件，awk将接受标准输入，并将结果显示在标准输出上。awk支持输入输出重定向。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; awk的记录、字段与内置变量：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前面说过，awk处理的工作与数据库的处理方式有相同之处，其相同处之一就是awk支持对记录和字段的处理，其中对字段的处理是grep和sed不能实现的，这也是awk优于二者的原因之一。在awk中，缺省的情况下总是将文本文件中的一行视为一个记录，而将一行中的某一部分作为记录中的一个字段。为了操作这些不同的字段，awk借用shell的方法，用$1,$2,$3&#8230;这样的方式来顺序地表示行（记录）中的不同字段。特殊地，awk用$0表示整个行（记录）。不同的字段之间是用称作分隔符的字符分隔开的。系统默认的分隔符是空格。awk允许在命令行中用-F re的形式来改变这个分隔符。事实上，awk用一个内置的变量FS来记忆这个分隔符。awk中有好几个这样的内置变量，例如，记录分隔符变量RS、当前工作的记录数NR等等，本文后面的附表列出了全部的内置变量。这些内置的变量可以在awk程序中引用或修改，例如，你可以利用NR变量在模式匹配中指定工作范围，也可以通过修改记录分隔符RS让一个特殊字符而不是换行符作为记录的分隔符。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例:显示文本文件myfile中第七行到第十五行中以字符%分隔的第一字段，第三字段和第七字段：</p>
<p>awk -F % &#8216;NR==7,NR==15 {printf $1 $3 $7}&#8217;</p>
<p>四、awk的内置函数</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; awk 之所以成为一种优秀的程序设计语言的原因之一是它吸收了某些优秀的程序设计语言（例如C）语言的许多优点。这些优点之一就是内置函数的使用，awk定义并支持了一系列的内置函数，由于这些函数的使用，使得awk提供的功能更为完善和强大，例如，awk使用了一系列的字符串处理内置函数(这些函数看起来与C 语言的字符串处理函数相似，其使用方式与C语言中的函数也相差无几)，正是由于这些内置函数的使用，使awk处理字符串的功能更加强大。本文后面的附录中列有一般的awk所提供的内置函数，这些内置函数也许与你的awk版本有些出入，因此，在使用之前，最好参考一下你的系统中的联机帮助。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 作为内置函数的一个例子，我们将在这里介绍awk的printf函数，这个函数使得awk与c语言的输出相一致。实际上，awk中有许多引用形式都是从C语言借用过来的。如果你熟悉C语言，你也许会记得其中的printf函数，它提供的强大格式输出功能曾经带我们许多的方便。幸运的是，我们在awk中又和它重逢了。awk中printf几乎与C语言中一模一样，如果你熟悉C语言的话，你完全可以照C语言的模式使用awk中的printf。因此在这里，我们只给出一个例子，如果你不熟悉的话，请随便找一本C语言的入门书翻翻。</p>
<p>例:显示文件myfile中的行号和第3字段：</p>
<p>$awk &#8216;{printf&#8221;%03d%sn&#8221;,NR,$1}&#8217; myfile</p>
<p>五、在命令行使用awk</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 按照顺序，我们应当讲解awk程序设计的内容了，但在讲解之前，我们将用一些例子来对前面的知识进行回顾，这些例子都是在命令行中使用的，由此我们可以知道在命令行中使用awk是多么的方便。这样做的原因一方面是为下面的内容作铺垫，另一方面是介绍一些解决简单问题的方法，我们完全没有必要用复杂的方法来解决简单的问题—-既然awk提供了较为简单的方法的话。</p>
<p>例：显示文本文件mydoc匹配（含有）字符串&#8221;sun&#8221;的所有行。</p>
<p>$awk &#8216;/sun/{print}&#8217; mydoc</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于显示整个记录（全行）是awk的缺省动作，因此可以省略action项。</p>
<p>$awk &#8216;/sun/&#8217; mydoc</p>
<p>例：下面是一个较为复杂的匹配的示例：</p>
<p>$awk &#8216;/[Ss]un/,/[Mm]oon/ {print}&#8217; myfile</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 它将显示第一个匹配Sun或sun的行与第一个匹配Moon或moon的行之间的行，并显示到标准输出上。</p>
<p>例：下面的示例显示了内置变量和内置函数length（）的使用：</p>
<p>$awk &#8216;length($0)&gt;80 {print NR}&#8217; myfile</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 该命令行将显示文本myfile中所有超过80个字符的行号，在这里，用$0表示整个记录（行），同时，内置变量NR不使用标志符&#8217;$'。</p>
<p>例：作为一个较为实际的例子，我们假设要对UNIX中的用户进行安全性检查，方法是考察/etc下的passwd文件，检查其中的passwd字段（第二字段）是否为&#8221;*&#8221;，如不为&#8221;*&#8221;，则表示该用户没有设置密码，显示出这些用户名（第一字段）。我们可以用如下语句实现：</p>
<p>#awk -F: &#8216;$2==&#8221;" {printf(&#8221;%s no password!n&#8221;,$1&#8242; /etc/passwd</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在这个示例中，passwd文件的字段分隔符是&#8220;：&#8221;，因此，必须用-F：来更改默认的字段分隔符，这个示例中也涉及到了内置函数printf的使用。</p>
<p>六、awk的变量</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如同其它程序设计语言一样，awk允许在程序语言中设置变量，事实上，提供变量的功能是程序设计语言的其本要求，不提供变量的程序设计语言本人还从未见过。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; awk 提供两种变量，一种是awk内置的变量，这前面我们已经讲过，需要着重指出的是，与后面提到的其它变量不同的是，在awk程序中引用内置变量不需要使用标志符&#8221;$&#8221;（回忆一下前面讲过的NR的使用）。awk提供的另一种变量是自定义变量。awk允许用户在awk程序语句中定义并调用自已的变量。当然这种变量不能与内置变量及其它awk保留字相同，在awk中引用自定义变量必须在它前面加上标志符&#8221;$&#8221;。与C语言不同的是，awk中不需要对变量进行初始化， awk根据其在awk中第一次出现的形式和上下文确定其具体的数据类型。当变量类型不确定时，awk默认其为字符串类型。这里有一个技巧：如果你要让你的 awk程序知道你所使用的变量的明确类型，你应当在在程序中给它赋初值。在后面的实例中，我们将用到这一技巧。</p>
<p>七、运算与判断</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 作为一种程序设计语言所应具有的特点之一，awk支持多种运算，这些运算与C语言提供的几本相同：如+、-、*、/、%等等，同时，awk也支持C语言中类似++、&#8211;、+=、-=、=+、=-之类的功能，这给熟悉C语言的使用者编写awk程序带来了极大的方便。作为对运算功能的一种扩展，awk还提供了一系列内置的运算函数（如log、sqr、cos、sin等等）和一些用于对字符串进行操作（运算）的函数（如length、substr等等）。这些函数的引用大大的提高了awk的运算功能。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 作为对条件转移指令的一部分，关系判断是每种程序设计语言都具备的功能，awk也不例外。 awk中允许进行多种测试，如常用的==（等于）、！=（不等于）、&gt;（大于）、&lt;（小于）、&gt;=（大于等于）、&gt;=（小于等于）等等，同时，作为样式匹配，还提供了~（匹配于）和！~（不匹配于）判断。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 作为对测试的一种扩充，awk也支持用逻辑运算符:!(非)、&amp;&amp;（与）、||（或）和括号（）进行多重判断，这大大增强了awk的功能。本文的附录中列出了awk所允许的运算、判断以及操作符的优先级。</p>
<p>八、awk的流程控制</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 流程控制语句是任何程序设计语言都不能缺少的部分。任何好的语言都有一些执行流程控制的语句。awk提供的完备的流程控制语句类似于C语言，这给我们编程带来了极大的方便。</p>
<p>1、BEGIN和END:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在awk 中两个特别的表达式，BEGIN和END，这两者都可用于pattern中（参考前面的awk语法），提供BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。任何在BEGIN之后列出的操作（在{}内）将在awk开始扫描输入之前执行，而END之后列出的操作将在扫描完全部的输入之后执行。因此，通常使用BEGIN来显示变量和预置（初始化）变量，使用END来输出最终结果。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例：累计销售文件xs中的销售金额（假设销售金额在记录的第三字段）：</p>
<p>$awk<br>&gt;&#8217;BEGIN { FS=&#8221;:&#8221;;print &#8220;统计销售金额&#8221;;total=0}<br>&gt;{print $3;total=total+$3;}<br>&gt;END {printf &#8220;销售金额总计：%.2f&#8221;,total}&#8217; sx<br>（注：&gt;是shell提供的第二提示符，如要在shell程序awk语句和awk语言中换行，则需在行尾加反斜杠）</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在这里，BEGIN预置了内部变量FS（字段分隔符）和自定义变量total,同时在扫描之前显示出输出行头。而END则在扫描完成后打印出总合计。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、流程控制语句</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; awk提供了完备的流程控制语句，其用法与C语言类似。下面我们一一加以说明：</p>
<p>2.1、if&#8230;else语句:</p>
<p>格式：<br>if(表达式)<br>语句1<br>else<br>语句2</p>
<p>格式中&#8221;语句1&#8243;可以是多个语句，如果你为了方便awk判断也方便你自已阅读，你最好将多个语句用{}括起来。awk分枝结构允许嵌套，其格式为：</p>
<p>if(表达式1）<br>{if(表达式2）<br>语句1<br>else<br>语句2<br>}<br>语句3<br>else {if(表达式3)<br>语句4<br>else<br>语句5<br>}<br>语句6</p>
<p>当然实际操作过程中你可能不会用到如此复杂的分枝结构，这里只是为了给出其样式罢了。</p>
<p>2.2、while语句</p>
<p>格式为:</p>
<p>while(表达式)<br>语句</p>
<p>2.3、do-while语句</p>
<p>格式为:</p>
<p>do<br>{<br>语句<br>}while(条件判断语句）</p>
<p>2.4、for语句</p>
<p>格式为：</p>
<p>for(初始表达式;终止条件;步长表达式)<br>{语句}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在awk 的 while、do-while和for语句中允许使用break,continue语句来控制流程走向，也允许使用exit这样的语句来退出。break 中断当前正在执行的循环并跳到循环外执行下一条语句。continue从当前位置跳到循环开始处执行。对于exit的执行有两种情况：当exit语句不在 END中时，任何操作中的exit命令表现得如同到了文件尾，所有模式或操作执行将停止，END模式中的操作被执行。而出现在END中的exit将导致程序终止。</p>
<p>例：为了</p>
<p>九、awk中的自定义函数</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 定义和调用用户自己的函数是几乎每个高级语言都具有的功能，awk也不例外，但原始的awk并不提供函数功能，只有在nawk或较新的awk版本中才可以增加函数。</p>
<p>函数的使用包含两部分：函数的定义与函数调用。其中函数定义又包括要执行的代码（函数本身）和从主程序代码传递到该函数的临时调用。</p>
<p>awk函数的定义方法如下：</p>
<p>function 函数名(参数表){<br>函数体<br>}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在gawk中允许将function省略为func，但其它版本的awk不允许。函数名必须是一个合法的标志符，参数表中可以不提供参数（但在调用函数时函数名后的一对括号仍然是不可缺少的），也可以提供一个或多个参数。与C语言相似，awk的参数也是通过值来传递的。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在awk 中调用函数比较简单，其方法与C语言相似，但awk比C语言更为灵活，它不执行参数有效性检查。换句话说，在你调用函数时，可以列出比函数预计（函数定义中规定）的多或少的参数，多余的参数会被awk所忽略，而不足的参数，awk将它们置为缺省值0或空字符串，具体置为何值，将取决于参数的使用方式。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; awk函数有两种返回方式：隐式返回和显式返回。当awk执行到函数的结尾时，它自动地返回到调用程序，这是函数是隐式返回的。如果需要在结束之前退出函数，可以明确地使用返回语句提前退出。方法是在函数中使用形如：return 返回值 格式的语句。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例：下面的例子演示了函数的使用。在这个示例中，定义了一个名为print_header的函数，该函数调用了两个参数FileName和PageNum， FileName参数传给函数当前使用的文件名，PageNum参数是当前页的页号。这个函数的功能是打印（显示）出当前文件的文件名，和当前页的页号。完成这个功能后，这个函数将返回下一页的页号。</p>
<p>nawk<br>&gt;&#8217;BEGIN{pageno=1;file=FILENAME<br>&gt;pageno=print_header(file，pageno)；#调用函数print_header<br>&gt;printf(&#8221;当前页页号是：%dn&#8221;,pageno);<br>&gt;}</p>
<p>&gt;#定义函数print_header<br>&gt;function print_header(FileName,PageNum){<br>&gt;printf(&#8221;%s %dn&#8221;,FileName,PageNum); &gt;PageNum++;return PageNUm;<br>&gt;}<br>&gt;}&#8217; myfile</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 执行这个程序将显示如下内容：</p>
<p>myfile 1<br>当前页页号是：2</p>
<p>十、awk高级输入输出</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.读取下一条记录：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; awk的next语句导致awk读取下一个记录并完成模式匹配，然后立即执行相应的操作。通常它用匹配的模式执行操作中的代码。next导致这个记录的任何额外匹配模式被忽略。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.简单地读取一条记录</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; awk 的 getline语句用于简单地读取一条记录。如果用户有一个数据记录类似两个物理记录，那么getline将尤其有用。它完成一般字段的分离(设置字段变量$0 FNR NF NR)。如果成功则返回1，失败则返回0（到达文件尾）。如果需简单地读取一个文件，则可以编写以下代码：</p>
<p>例：示例getline的使用</p>
<p>{while(getline==1)<br>{<br>#process the inputted fields<br>}<br>}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 也可以使getline保存输入数据在一个字段中，而不是通过使用getline variable的形式处理一般字段。当使用这种方式时，NF被置成0，FNR和NR被增值。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用户也可以使用getline&lt;"filename"方式从一个给定的文件中输入数据，而不是从命令行所列内容输入数据。此时，getline将完成一般字段分离（设置字段变量$0和NF)。如果文件不存在，返回-1,成功，返回1,返回0表示失败。用户可以从给定文件中读取数据到一个变量中，也可以用stdin(标准输入设备）或一个包含这个文件名的变量代替filename。值得注意的是当使用这种方式时不修改FNR和NR。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 另一种使用getline语句的方法是从UNIX命令接受输入，例如下面的例子:</p>
<p>例：示例从UNIX命令接受输入</p>
<p>{while("who -u"|getline)<br>{<br>#process each line from the who command<br>}<br>}</p>
<p>当然，也可以使用如下形式:</p>
<p>"command" | getline variable</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.关闭文件:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; awk中允许在程序中关闭一个输入或输出文件，方法是使用awk的close语句。</p>
<p>close("filename"t</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; filename可以是getline打开的文件（也可以是stdin,包含文件名的变量或者getline使用的确切命令）。或一个输出文件（可以是stdout，包含文件名的变量或使用管道的确切命令）。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.输出到一个文件:</p>
<p>awk中允许用如下方式将结果输出到一个文件：</p>
<p>printf("hello word!n"t&gt;&#8220;datafile&#8221;<br>或<br>printf(&#8221;hello word!n&#8221;t&gt;&gt;&#8221;datafile&#8221;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5.输出到一个命令</p>
<p>awk中允许用如下方式将结果输出到一个命令：</p>
<p>printf(&#8221;hello word!n&#8221;t|&#8221;sort-t&#8217;,'&#8221;</p>
<p>十一、awk与shell script混合编程</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 因为awk可以作为一个shell命令使用，因此awk能与shell批处理程序很好的融合在一起，这给实现awk与shell程序的混合编程提供了可能。实现混合编程的关键是awk与shell script之间的对话，换言之，就是awk与shell script之间的信息交流:awk从shell script中获取所需的信息（通常是变量的值）、在awk中执行shell命令行、shell script将命令执行的结果送给awk处理以及shell script读取awk的执行结果等等。</p>
<p>1.awk读取Shell script程序变量</p>
<p>在awk中我们可以通过&#8220;&#8217;$变量名&#8217;&#8221;的方式读取sell scrpit程序中的变量。</p>
<p>例：在下面的示例中，我们将读取sell scrpit程序中的变量Name，该变量存放的是文本myfile的撰写者，awk将打印出这个人名。</p>
<p>$cat writename<br>:<br># @(#)<br>#<br>.<br>.<br>.<br>Name=&#8221;张三&#8221; nawk &#8216;BEGIN {name=&#8221;&#8216;Name&#8217;&#8221;; printf(&#8221;t%st撰写者%sn&#8221;,FILENAME,name&#8221;t;}<br>{&#8230;}END{&#8230;}&#8217; myfile<br>.<br>.<br>.</p>
<p>2.将shell命令的执行结果送给awk处理</p>
<p>作为信息传送的一种方法，我们可以将一条shell命令的结果通过管道线（|）传递给awk处理：</p>
<p>例：示例awk处理shell命令的执行结果</p>
<p>$who -u | awk &#8216;{printf(&#8221;%s正在执行%sn&#8221;,$2,$1)}&#8217;</p>
<p>该命令将打印出注册终端正在执行的程序名。</p>
<p>3.shell script程序读awk的执行结果</p>
<p>为了实现shell script程序读取awk执行的结果，我们可以采取一些特殊的方法，例如我们可以用变量名=`awk语句`的形式将awk执行的结果存放入一个 shell script变量。当然也可以用管道线的方法将awk执行结果传递给shell script程序处理。</p>
<p>例：作为传送消息的机制之一，UNIX提供了一个向其所有用户传送消息的命令wall（意思是write to all写给所有用户），该命令允许向所有工作中的用户（终端）发送消息。为此，我们可以通过一段shell批处理程序wall.shell来模拟这一程序（事实上比较老的版本中wall就是一段shell批处理程序：</p>
<p>$cat wall.shell<br>:<br># @(#) wall.shell:发送消息给每个已注册终端<br>#<br>cat &gt;/tmp/$$<br>#用户录入消息文本 who -u | awk &#8216;{print $2}&#8217; | while read tty<br>do<br>cat /tmp/$$&gt;$tty<br>done</p>
<p>在这个程序里，awk接受who -u命令的执行结果，该命令打印出所有已注册终端的信息，其中第二个字段是已注册终端的设备名，因此用awk命令析出该设备名，然后用while read tty语句循环读出这些文件名到变量（shell script变量）tty中，作为信息传送的终结地址。</p>
<p>4.在awk中执行shell命令行—-嵌入函数system()</p>
<p>system()是一个不适合字符或数字类型的嵌入函数，该函数的功能是处理作为参数传递给它的字符串。system对这个参数的处理就是将其作为命令处理，也就是说将其当作命令行一样加以执行。这使得用户在自己的awk程序需要时可以灵活地执行命令或脚本。</p>
<p>例：下面的程序将使用system嵌入函数打印用户编制好的报表文件，这个文件存放在名为myreport.txt的文件中。为简约起见，我们只列出了其END部分：</p>
<p>.<br>.<br>.<br>END {close(&#8221;myreport.txt&#8221;t;system(&#8221;lp myreport.txt&#8221;t;}</p>
<p>在这个示例中，我们首先使用close语句关闭了文件myreport.txt文件，然后使用system嵌入函数将myreport.txt送入打印机打印。</p>
<p>写到这里，我不得不跟朋友们说再见了，实在地说，这些内容仍然是awk的初步知识，电脑永远是前进的科学，awk也不例外，本篇所能做的只是在你前行的漫漫长途中铺平一段小小开端，剩下的路还得靠你自己去走。老实说，如果本文真能给你前行的路上带来些许的方便，那本人就知足了！</p>
<p>如对本篇有任何疑问，请E-mail To:Chizlong@yeah.net或到主页<a href="http://chizling.yeah.net/"><u><font color=#0000ff>http://chizling.yeah.net</font></u></a>中留言。<br>附录：</p>
<p>1.awk的常规表达式元字符</p>
<p>换码序列<br>^ 在字符串的开头开始匹配<br>$ 在字符串的结尾开始匹配<br>. 与任何单个字符串匹配<br>[ABC] 与[]内的任一字符匹配<br>[A-Ca-c] 与A-C及a-c范围内的字符匹配（按字母表顺序）<br>[^ABC] 与除[]内的所有字符以外的任一字符匹配<br>Desk|Chair 与Desk和Chair中的任一个匹配<br>[ABC][DEF] 关联。与A、B、C中的任一字符匹配，且其后要跟D、E、F中的任一个字符。<br>* 与A、B或C中任一个出现0次或多次的字符相匹配<br>+ 与A、B或C中任何一个出现1次或多次的字符相匹配<br>？ 与一个空串或A、B或C在任何一个字符相匹配<br>（Blue|Black）berry 合并常规表达式，与Blueberry或Blackberry相匹配</p>
<p>2.awk算术运算符</p>
<p>运算符 用途<br>——————<br>x^y x的y次幂<br>x**y 同上<br>x%y 计算x/y的余数（求模）<br>x+y x加y<br>x-y x减y<br>x*y x乘y<br>x/y x除y<br>-y 负y(y的开关符号);也称一目减<br>++y y加1后使用y(前置加）<br>y++ 使用y值后加1（后缀加）<br>&#8211;y y减1后使用y(前置减）<br>y&#8211; 使用后y减1(后缀减）<br>x=y 将y的值赋给x<br>x+=y 将x+y的值赋给x<br>x-=y 将x-y的值赋给x<br>x*=y 将x*y的值赋给x<br>x/=y 将x/y的值赋给x x%=y 将x%y的值赋给x<br>x^=y 将x^y的值赋给x<br>x**=y 将x**y的值赋给x</p>
<p>3.awk允许的测试：</p>
<p>操作符 含义</p>
<p>x==y x等于y<br>x!=y x不等于y<br>x&gt;y x大于y<br>x&gt;=y x大于或等于y<br>xx&lt;=y x小于或等于y?<br>x~re x匹配正则表达式re?<br>x!~re x不匹配正则表达式re?</p>
<p>4.awk的操作符(按优先级升序排列)</p>
<p>= 、+=、 -=、 *= 、/= 、 %=<br>||<br>&amp;&amp;<br>&gt; &gt;= &lt; &lt;= == != ~ !~<br>xy (字符串连结，&#8217;x'&#8217;y'变成&#8221;xy&#8221;）<br>+ -<br>* / %<br>++ &#8211;</p>
<p>5.awk内置变量（预定义变量）</p>
<p>说明：表中v项表示第一个支持变量的工具（下同）：A=awk，N=nawk,P=POSIX awk,G=gawk</p>
<p>V 变量 含义 缺省值<br>——————————————————&#8211;<br>N ARGC 命令行参数个数<br>G ARGIND 当前被处理文件的ARGV标志符<br>N ARGV 命令行参数数组<br>G CONVFMT 数字转换格式 %.6g<br>P ENVIRON UNIX环境变量<br>N ERRNO UNIX系统错误消息<br>G FIELDWIDTHS 输入字段宽度的空白分隔字符串<br>A FILENAME 当前输入文件的名字<br>P FNR 当前记录数<br>A FS 输入字段分隔符 空格<br>G IGNORECASE 控制大小写敏感0（大小写敏感）<br>A NF 当前记录中的字段个数<br>A NR 已经读出的记录数<br>A OFMT 数字的输出格式 %.6g<br>A OFS 输出字段分隔符 空格<br>A ORS 输出的记录分隔符 新行<br>A RS 输入的记录他隔符 新行<br>N RSTART 被匹配函数匹配的字符串首<br>N RLENGTH 被匹配函数匹配的字符串长度<br>N SUBSEP 下标分隔符 &#8220;34&#8243;</p>
<p>6.awk的内置函数</p>
<p>V 函数 用途或返回值<br>————————————————<br>N gsub(reg,string,target) 每次常规表达式reg匹配时替换target中的string<br>N index(search,string) 返回string中search串的位置<br>A length(string) 求串string中的字符个数<br>N match(string,reg) 返回常规表达式reg匹配的string中的位置<br>N printf(format,variable) 格式化输出，按format提供的格式输出变量variable。<br>N split(string,store,delim) 根据分界符delim,分解string为store的数组元素<br>N sprintf(format,variable) 返回一个包含基于format的格式化数据，variables是要放到串中的数据<br>G strftime(format,timestamp) 返回一个基于format的日期或者时间串，timestmp是systime()函数返回的时间<br>N sub(reg,string,target) 第一次当常规表达式reg匹配，替换target串中的字符串<br>A substr(string,position,len) 返回一个以position开始len个字符的子串<br>P totower(string) 返回string中对应的小写字符<br>P toupper(string) 返回string中对应的大写字符<br>A atan(x,y) x的余切(弧度)<br>N cos(x) x的余弦(弧度)<br>A exp(x) e的x幂<br>A int(x) x的整数部分<br>A log(x) x的自然对数值<br>N rand() 0-1之间的随机数<br>N sin(x) x的正弦(弧度)<br>A sqrt(x) x的平方根<br>A srand(x) 初始化随机数发生器。如果忽略x，则使用system()<br>G system() 返回自1970年1月1日以来经过的时间（按秒计算） </p>
<img src ="http://www.cppblog.com/megax/aggbug/44178.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/megax/" target="_blank">megax</a> 2008-03-11 14:08 <a href="http://www.cppblog.com/megax/articles/44178.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]grep 用法</title><link>http://www.cppblog.com/megax/articles/44177.html</link><dc:creator>megax</dc:creator><author>megax</author><pubDate>Tue, 11 Mar 2008 06:07:00 GMT</pubDate><guid>http://www.cppblog.com/megax/articles/44177.html</guid><wfw:comment>http://www.cppblog.com/megax/comments/44177.html</wfw:comment><comments>http://www.cppblog.com/megax/articles/44177.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/megax/comments/commentRss/44177.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/megax/services/trackbacks/44177.html</trackback:ping><description><![CDATA[<p>这组命令以指定模式搜索文件，并通知用户在什么文件中搜索到与指定的模式匹配的字符串，并打印出所有包含该字符串的文本行，在该文本行的最前面是该行所在的文件名。 grep 命令一次只能搜索一个指定的模式；egrep 命令检索扩展的正则表达式（包括表达式组和可选项）；fgrep 命令检索固定字符串，它不识别正则表达式，是快速搜索命令。</p>
<p><a id=more-38></a></p>
<p>这组命令在搜索与定位文件中特定的主题方面非常有用。要搜索的模式可以被认为是一些关键词，您可以用它们来搜索文件中包含的这些关键词。编写程序时，可以用它来寻找某一个函数，或是相关的词组。grep 命令的搜索功能比 fgrep 强大，因为 grep 命令的搜索模式可以是正则表达式，而 fgrep 却不能。</p>
<p>该组命令中的每一个命令都有一组选项，利用这些选项可以改变其输出方式。例如，可以在搜索到的文本行上加入行号，或者只输出文本行的行号，或者输出所有与搜索模式不匹配的文本行，或只简单地输出已搜索到指定模式的文件名，并且可以指定在查找模式时忽略大小写。</p>
<p>这组命令在指定氖淙胛募胁檎矣肽Ｊ狡ヅ涞男小Ｈ绻挥兄付ㄎ募虼颖曜际淙?中读取。正常情况下，每个匹配的行被显示到标准输出。如果要查找的文件是多个，则在每一行输出之前加上文件名。</p>
<pre>语法：  grep [选项] [查找模式] [文件名1，文件名2，&#8230;&#8230;]  egrep [选项] [查找模式] [文件名1，文件名2，&#8230;&#8230;]  fgrep [选项] [查找模式] [文件名1，文件名2，&#8230;&#8230;]</pre>
<p><strong>该命令的各选项含义如下：</strong></p>
<pre>-E 每个模式作为一个扩展的正则表达式对待。 -F 每个模式作为一组固定字符串对待（以新行分隔），而不作为正则表达式。 -b 在输出的每一行前显示包含匹配字符串的行在文件中的字节偏移量。 -c 只显示匹配行的数量。 -i 比较时不区分大小写。 -h 在查找多个文件时，指示grep不要将文件名加入到输出之前。 -l 显示首次匹配串所在的文件名并用换行符将其隔开。    当在某文件中多次出现匹配串时，不重复显示此文件名。 -n 在输出前加上匹配串所在行的行号（文件首行行号为1）。 -v 只显示不包含匹配串的行。 -x 只显示整行严格匹配的行。 -e expression 指定检索使用的模式。用于防止以&#8220;-&#8221;开头的模式被解释为命令选项。 -f expfile 从expfile文件中获取要搜索的模式，一个模式占一行。</pre>
<p>对该组命令的使用还需注意以下方面：</p>
<p style="TEXT-INDENT: 0px">在命令后键入搜索的模式，再键入要搜索的文件。其中，文件名列表中也可以使用特殊字符，如 &#8220;*&#8221; 等，用来生成文件名列表。如果想在搜索的模式中包含有空格的字符串，可以用单引号把要搜索的模式括起来，用来表明搜索的模式是由包含空格的字符串组成。否则，Shell 将把空格认为是命令行参数的定界符，而 grep 命令将把搜索模式中的单词解释为文件名列表中的一部分。在下面的例子中，grep 命令在文件 example 中搜索模式 &#8220;text file&#8221;。</p>
<pre>grep &#8217;text file&#8217; example</pre>
<p style="TEXT-INDENT: 0px">用户可以在命令行上用Shell特殊字符来生成将要搜索的文件名列表。在下面的例子中，特殊字符&#8220;*&#8221;用来生成一个文件名列表，该列表包含当前目录下所有的文件。该命令将搜索出当前目录下所有文件中与模式匹配的行。</p>
<pre>grep data *</pre>
<p style="TEXT-INDENT: 0px">特殊字符在搜索一组指定的文件时非常有用。例如，如果想搜索所有的C程序源文件中特定的模式，您可以用&#8220;*.c&#8221;来指定文件名列表。假设用户的 C程序中包含一些不必要的转向语句（goto语句），想要找到这些语句，可以用如下的命令来搜索并显示所有包含 goto语句的代码行：</p>
<pre>grep goto *.c</pre>
<p style="TEXT-INDENT: 0px">用户可以在命令行上键入搜索模式，也可以使用 -f 选项从指定文件中读取要搜索的模式。在文件中，每个搜索模式占一行。如果经常要搜索一组常见字符串时，这个功能非常有用。在下面的例子中，用户要在文件 exam 中搜索字符串 &#8220;editor&#8221; 和 &#8220;create&#8221;，就把要搜索的模式放置在文件 mypats 中，然后，grep 命令从文件 mypats 中读取要搜索的模式。</p>
<pre>grep -f mypats exam</pre>
<img src ="http://www.cppblog.com/megax/aggbug/44177.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/megax/" target="_blank">megax</a> 2008-03-11 14:07 <a href="http://www.cppblog.com/megax/articles/44177.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]gawk 手册</title><link>http://www.cppblog.com/megax/articles/44176.html</link><dc:creator>megax</dc:creator><author>megax</author><pubDate>Tue, 11 Mar 2008 06:06:00 GMT</pubDate><guid>http://www.cppblog.com/megax/articles/44176.html</guid><wfw:comment>http://www.cppblog.com/megax/comments/44176.html</wfw:comment><comments>http://www.cppblog.com/megax/articles/44176.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/megax/comments/commentRss/44176.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/megax/services/trackbacks/44176.html</trackback:ping><description><![CDATA[<p>备注：</p>
<ul>
    <li>当把awk代码存储到文件中的时候，&#8217;是不需要的，即开头和末尾均不需要&#8217;。
    <li>一下为参考链接：
    <li><a href="http://fanqiang.chinaunix.net/program/shell/2005-03-30/3068.shtml"><u><font color=#0000ff>http://fanqiang.chinaunix.net/program/shell/2005-03-30/3068.shtml</font></u></a>
    <li><a href="http://fanqiang.chinaunix.net/program/shell/index.shtml"><u><font color=#0000ff>http://fanqiang.chinaunix.net/program/shell/index.shtml</font></u></a>
    <li><a href="http://www.linuxsir.org/bbs/showthread.php?t=184399"><u><font color=#0000ff>http://www.linuxsir.org/bbs/showthread.php?t=184399</font></u></a> </li>
</ul>
<p><a id=more-35></a></p>
<p>GAWK</p>
<p>第一章 前言<br>第二章 简介<br>第三章 读取输入档案<br>第四章 印出<br>第五章 Patterns<br>第六章 算式(Expression)作为Actions的叙述<br>第七章 Actions里面的控制叙述<br>第八章 内建函式(Built-in Functions)<br>第九章 使用者定义的函式<br>第十章 □例<br>第十一章 结论<br>＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝</p>
<p>第一章 前言</p>
<p>awk 是一个程式语言，对於资料的处理具有很强的功能。对於文<br>字档里的资料做修改、比对、抽取等的处理，awk 能够以很短的程式<br>轻易地完成。如果使用 C 或 Pascal 等语言写程式完成上述的动作，<br>会不方便且很花费时间，所写的程式也会很大。</p>
<p>awk 能够依照使用者的定义格式来分解输入资料，也可依照使用<br>者定义的格式来印出资料。</p>
<p>awk 名称的由来是由它的原始设计者的姓氏之第一个字母而命名<br>：Alfred V. Aho, Peter J. Weinberger, Brian W. Kernighan。<br>awk最初在1977年完成。一个新版本的awk在1985年被发表，它的功能<br>比旧版本增强不少。</p>
<p>gawk 是GNU所做的 awk，gawk 最初在1986年完成，之後不断地<br>被改进、更新。gawk 包含 awk 的所有功能。</p>
<p>往後的 gawk 将以下面的2个输入档案来做例子说明。</p>
<p>档案&#8217;BBS-list&#8217;：<br>aardvark 555-5553 1200/300 B<br>alpo-net 555-3412 2400/1200/300 A<br>barfly 555-7685 1200/300 A<br>bites 555-1675 2400/1200/300 A<br>camelot 555-0542 300 C<br>core 555-2912 1200/300 C<br>fooey 555-1234 2400/1200/300 B<br>foot 555-6699 1200/300 B<br>macfoo 555-6480 1200/300 A<br>sdace 555-3430 2400/1200/300 A<br>sabafoo 555-2127 1200/300 C</p>
<p>档案&#8217;shipped&#8217;：<br>Jan 13 25 15 115<br>Feb 15 32 24 226<br>Mar 15 24 34 228<br>Apr 31 52 63 420<br>May 16 34 29 208<br>Jun 31 42 75 492<br>Jul 24 34 67 436<br>Aug 15 34 47 316<br>Sep 13 55 37 277<br>Oct 29 54 68 525<br>Nov 20 87 82 577<br>Dec 17 35 61 401</p>
<p>Jan 21 36 64 620<br>Feb 26 58 80 652<br>Mar 24 75 70 495<br>Apr 21 70 74 514<br>第二章 简介</p>
<p>gawk 的主要功能是针对档案的每一行(line)搜寻指定的 patterns<br>。当一行里有符合指定的 patterns，gawk 就会在此一行执行被指定<br>的 actions。 gawk 依此方式处理输入档案的每一行直到输入档案结<br>束。</p>
<p>gawk 程式是由很多的 pattern 与 action 所组成，action 写在<br>大括号 { } 里面，一个pattern後面就跟著一个action。整个 gawk 程<br>式会像下面的样子：</p>
<p>pattern {action}<br>pattern {action}</p>
<p>在 gawk 程式里面的规则，pattern 或 action 能够被省略，但<br>是两个不能同时被省略。如果 pattern 被省略，对於输入档里面的<br>每一行，action 都会被执行。如果 action 被省略，内定的 action<br>则会印出所有符合 pattern 的输入行。<br>2.1 如何执行gawk程式</p>
<p>基本上，有2个方法可以执行gawk程式。</p>
<p>□如果 gawk 程式很短，则 gawk 可以直接写在 command line，如下所示：</p>
<p>gawk &#8216;program&#8217; input-file1 input-file2 &#8230;</p>
<p>其中 program 包括一些 pattern 和 action。</p>
<p>□如果 gawk 程式较长，较为方便的做法是将 gawk 程式存在一个档案，<br>即 patterns 与 actions 写在档名为 program-file 的档案里面，执行<br>gawk 的格式如下所示：</p>
<p>gawk -f program-file input-file1 input-file2 &#8230;</p>
<p>gawk 程式的档案不止一个时，执行gawk 的格式如下所示：</p>
<p>gawk -f program-file1 -f program-file2 &#8230; input-file1<br>input-file2 &#8230;<br>2.2 一个简单的例子</p>
<p>现在我们举一个简单的例子，因为 gawk 程式很短，所以将 gawk 程<br>式直接写在 command line。</p>
<p>gawk &#8216;/foo/ {print $0}&#8217; BBS-list</p>
<p>实际的 gawk 程式为 /foo/ {print $0}。/foo/ 为 pattern，意思为搜<br>寻输入档里的每一行是否含有子字串 &#8216;foo&#8217;，如果含有 &#8216;foo&#8217; 则执行 action。<br>action 为 print $0，是将现在这一行的内容印出。BBS-list 是输入的档案。</p>
<p>执行完上述指令後，会印出下面的结果：<br>fooey 555-1234 2400/1200/300 B<br>foot 555-6699 1200/300 B<br>macfoo 555-6480 1200/300 A<br>sabafoo 555-2127 1200/300 C<br>2.3 一个较复杂的例子</p>
<p>gawk &#8216;$1 == &#8220;Feb&#8221; {sum=$2+$3} END {print sum}&#8217; shipped</p>
<p>现在这个例子会将输入档 &#8217;shipped&#8217; 的第一个栏位与 &#8220;Feb&#8221; 做比较<br>，如果相等，则其对应的第2栏位与第3栏位的值会被加到变数 sum。<br>对於输入档的每一行重复上述的动作，直到输入档的每一行都被处理<br>过为止。最後将 sum 的值印出。END {print sum} 的意思为在所有的输<br>入读完之後，执行一次 print sum 的动作，也就是把 sum 的值印出。</p>
<p>下面是执行的结果：<br>84<br>第三章 读取输入档案</p>
<p>gawk的输入可以从标准输入或指定的档案里读取。输入的读取单<br>位被称为&#8221;记录&#8221;(records)，gawk 在做处理时，是一个记录一个记<br>录地处理。每个记录的内定值是一行(line)，一个记录又被分为多个<br>栏位(fields)。<br>3.1 如何将输入分解成记录(records)</p>
<p>gawk 语言会把输入分解成记录(record)。记录与记录之间是以<br>record separator 隔开，record separator 的内定值是表示新一行的<br>字元(newline character)，因此内定的 record separator 使得文字<br>的每一行是一个记录。</p>
<p>record separator 随著内建变数 RS 的改变而改变。RS 是一个字串，<br>它的内定值是&#8221;\n&#8221;。仅有 RS 的第一个字元是有效的，它被当作 record<br>separator，而 RS 的其它字元会被忽略。</p>
<p>内建变数 FNR 会储存目前的输入档案已经被读取的记录之个数。内<br>建变数 NR 会储存目前为止所有的输入档案已经被读取的记录之个数。<br>3.2 栏位(field)</p>
<p>gawk 会自动将每个记录分解成多个栏位 (field)。类似於字在一<br>行里面，gawk 的内定动作会认为栏位之间是以 whitespace 分开。在<br>gawk 里，whitespace 的意思是一个或多个空白或 tabs。</p>
<p>在 gawk 程式里面，以&#8217;$1&#8242;表示第一个栏位，&#8217;$2&#8242;表示第二个栏位<br>，依此类推。举个例子，假设输入的一行如下所示：</p>
<p>This seems like a pretty nice example.</p>
<p>第一个栏位或 $1 是&#8217;This&#8217;，第二个栏位或 $2 是 &#8217;seems&#8217;，依此类推。<br>有个地方值得特别注意，第七个栏位或 $7 是&#8217;example.&#8217;而非&#8217;example&#8217;。</p>
<p>不论有多少栏位，$NF 可用来表示一个记录的最後一个栏位。以<br>上面的例子为例，$NF 与 $7 相同，也就是&#8217;example.&#8217;。</p>
<p>NF 是一个内建变数，它的值表示目前这个记录之栏位的个数。</p>
<p>$0，看起来好像是第零个栏位，它是一个特例，它表示整个记录。</p>
<p>下面是一个较复杂的例子：</p>
<p>gawk &#8216;$1~/foo/ {print $0}&#8217; BBS-list</p>
<p>结果如下：<br>fooey 555-1234 2400/1200/300 B<br>foot 555-6699 1200/300 B<br>macfoo 555-6480 1200/300 A<br>sabafoo 555-2127 1200/300 C</p>
<p>这个例子是把输入档&#8217;BBS-list&#8217;的每个记录的第一个栏位作检查，如<br>果它含有子字串&#8217;foo&#8217;，则这一个记录会被印出。<br>3.3 如何将记录分解成栏位</p>
<p>gawk 根据 field separator 将一个记录分解成栏位。field sepa-<br>rator 以内建变数 FS 表示。</p>
<p>举个例子，假如 field separator 是&#8217;oo&#8217;，则下面的行：</p>
<p>moo goo gai pan</p>
<p>会被分成三个栏位：&#8217;m'、&#8217; g&#8217;、&#8217; gai pan&#8217;。</p>
<p>在 gawk 程式里，可以使用&#8217;='来改变 FS 的值。例如:</p>
<p>gawk &#8216;BEGIN {FS=&#8221;,&#8221;}; {print $2}&#8217;</p>
<p>输入行如下：</p>
<p>John Q. Smith, 29 Oak St., Walamazoo, MI 42139</p>
<p>执行gawk的结果将印出字串 &#8216; 29 Oak St.&#8217;。BEGIN 後面的 action 会在<br>第一个记录被读取之前执行一次。<br>第四章 印出</p>
<p>在gawk程式里，actions 最常做的事就是印出(printing)。简单<br>的印出，使用 printe叙述。复杂格式的印出，使用 printf 叙述。<br>4.1 print叙述</p>
<p>print 叙述用在简单、标准的输出格式。叙述的格式如下所示：</p>
<p>print item1, item2, &#8230;</p>
<p>输出时，各个 item 之间会以一个空白分开，最後会换行(newline)。</p>
<p>如果 &#8216;print&#8217;叙述之後没有跟著任何东西，它与&#8217;print $0&#8242;的效<br>果一样，它会印出现在的记录(record)。要印出空白行可使用&#8217;print<br>&#8220;&#8221;&#8216;。 印出一段固定的文字，可用双引号将文字的两边括起来，例如<br>&#8216;print &#8220;Hello there&#8221;&#8216;。</p>
<p>这里是一个例子，它会把每个输入记录的前二个栏位印出：</p>
<p>gawk &#8216;{print $1,$2}&#8217; shipped</p>
<p>结果如下所示：<br>Jan 13<br>Feb 15<br>Mar 15<br>Apr 31<br>May 16<br>Jun 31<br>Jul 24<br>Aug 15<br>Sep 13<br>Oct 29<br>Nov 20<br>Dec 17</p>
<p>Jan 21<br>Feb 26<br>Mar 24<br>Apr 21<br>4.2 Output Separators</p>
<p>前面我们已提过如果 print 叙述包含有多个 item，item 之间<br>用逗点分开，则印出时各个item会被一个空白隔开。你能够使用任何<br>的字串作为 output field separator，可以经由内建变数 OFS 的设<br>定来更改 output field separator。OFS 的初始值为&#8221; &#8220;，即一格的<br>空白。</p>
<p>整个 print 叙述的输出被称为 output record。print 叙述输<br>出 output record 之後，会接著输出一个字串，此字串称为 output<br>record separator。内建变数 ORS 用来指明此字串。ORS 的初始值<br>为 &#8220;\n&#8221;，也就是换行。</p>
<p>下面这个例子会印出每个记录的第一个栏位和第二个栏位，此二<br>个栏位之间以分号&#8217;;'分开，每行输出之後会加入一个空白行。</p>
<p>gawk &#8216;BEGIN {OFS=&#8221;;&#8221;; ORS=&#8221;\n\n&#8221;} {print $1, $2}&#8217; BBS-list</p>
<p>结果如下所示：<br>aardvark;555-5553</p>
<p>alpo-net;555-3412</p>
<p>barfly;555-7685</p>
<p>bites;555-1675</p>
<p>camelot;555-0542</p>
<p>core;555-2912</p>
<p>fooey;555-1234</p>
<p>foot;555-6699</p>
<p>macfoo;555-6480</p>
<p>sdace;555-3430</p>
<p>sabafoo;555-2127</p>
<p>&nbsp;</p>
<p>4.3 printf叙述</p>
<p>printf 叙述会使得输出格式较容易精确地控制。printf 叙述可以<br>指定每个 item 印出的宽度，也可以指定数字的各种型式。</p>
<p>printf 叙述的格式如下：</p>
<p>printf format, item1, item2, &#8230;</p>
<p>print 与 printf 的差别是在於 format, printf 的引数比 print<br>多了字串 format。format 的型式与 ANSI C 的 printf 之格式相同。</p>
<p>printf 并不会做自动换行的动作。内建变数 OFS 与 ORS 对 printf 叙<br>述没有任何影响。</p>
<p>格式的指定以字元&#8217;%'开始，後面接著格式控制字母。</p>
<p>格式控制字母如下所示：</p>
<p>&#8216;c&#8217; 将数字以 ASCII 字元印出。<br>例如&#8217;printf &#8220;%C&#8221;,65&#8242;会印出字元&#8217;A'。</p>
<p>&#8216;d&#8217; 印出十进位的整数。</p>
<p>&#8216;i&#8217; 印出十进位的整数。</p>
<p>&#8216;e&#8217; 将数字以科学符号的形式印出。<br>例如</p>
<p>print &#8220;$4.3e&#8221;,1950</p>
<p>结果会印出&#8217;1.950e+03&#8242;。</p>
<p>&#8216;f&#8217; 将数字以浮点的形式印出。</p>
<p>&#8216;g&#8217; 将数字以科学符号的形式或浮点的形式印出。数字的绝对值如果<br>大於等於0.0001则以浮点的形式印出，否则以科学符号的形式印<br>出。</p>
<p>&#8216;o&#8217; 印出无号的八进位整数。</p>
<p>&#8217;s&#8217; 印出一个字串。</p>
<p>&#8216;x&#8217; 印出无号的十六进位整数。10至15以&#8217;a'至&#8217;f'表示。</p>
<p>&#8216;X&#8217; 印出无号的十六进位整数。10至15以&#8217;A'至&#8217;F&#8221;表示。</p>
<p>&#8216;%&#8217; 它并不是真正的格式控制字母，&#8217;%%&#8221;将印出&#8221;%&#8217;。</p>
<p>在 % 与格式控制字母之间可加入 modifier，modifier 是用来进一<br>步控制输出的格式。可能的 modifier 如下所示：</p>
<p>&#8216;-&#8217; 使用在 width 之前，指明是向左靠齐。如果&#8217;-'没有出现，则会在<br>被指定的宽度向右靠齐。例如：</p>
<p>printf &#8220;%-4S&#8221;, &#8220;foo&#8221;</p>
<p>会印出&#8217;foo &#8216;。</p>
<p>&#8216;width&#8217; 这一个数字指示相对应的栏位印出时的宽度。例如：</p>
<p>printf &#8220;%4s&#8221;,&#8221;foo&#8221;</p>
<p>会印出&#8217; foo&#8217;。</p>
<p>width 的值是一个最小宽度而非最大宽度。如果一个 item 的<br>值需要的宽度比 width 大，则不受 width 的影响。例如</p>
<p>printf &#8220;%4s&#8221;,&#8221;foobar&#8221;</p>
<p>将印出&#8217;foobar&#8217;。</p>
<p>&#8216;.prec&#8217; 此数字指定印出时的精确度。它指定小数点右边的位数。如<br>果是要印出一个字串，它指定此字串最多会被印出多少个字<br>元。<br>第五章 patterns</p>
<p>在 gawk 程式里面，当 pattern 符合现在的输入记录(record)，其<br>相对应的 action 才会被执行。<br>5.1 Pattern的种类</p>
<p>这里对 gawk 的各种 pattern 型式作一整理：</p>
<p>/regular expression/<br>一个 regular expression 当作一个 pattern。每当输入记录 (<br>record)含有 regular expression 就视为符合。</p>
<p>expression<br>一个单一的 expression。当一个值不为 0 或一个字串不是空的，<br>则可视为符合。</p>
<p>pat1,pat2<br>一对的 patterns 以逗号分开，指定记录的□围。</p>
<p>BEGIN<br>END<br>这是特别的 pattern, gawk 在开始执行或要结束时会分别执行相<br>对应於BEGIN或END的 action。</p>
<p>null<br>这是一个空的pattern，对於每个输入记录皆视为符合pattern。<br>5.2 Regular Expressions当作Patterns</p>
<p>一个 regular expression 可简写为 regexp，是一种描述字串的方<br>法。一个 regular expression 以斜线(&#8217;/')包围当作 gawk 的 pattern。</p>
<p>如果输入记录含有 regexp 就视为符合。例如：pattern 为 /foo/，<br>对於任何输入记录含有&#8217;foo&#8217;则视为符合。</p>
<p>下面的例子会将含有&#8217;foo&#8217;的输入记录之第2个栏位印出。</p>
<p>gawk &#8216;/foo/ {print $2}&#8217; BBS-list</p>
<p>结果如下：<br>555-1234<br>555-6699<br>555-6480<br>555-2127</p>
<p>regexp 也能使用在比较的算式。</p>
<p>exp ~ /regexp/<br>如果 exp 符合 regexp，则结果为真(true)。</p>
<p>exp !~ /regexp/<br>如果 exp 不符合 regexp，则结果为真。<br>5.3 比较的算式当作Patterns</p>
<p>比较的 pattern 用来测试两个数字或字串的关系诸如大於、等於<br>、小於。下面列出一些比较的pattern：</p>
<p>x<y 如果 x 小於 y，则结果为真。<br /> x&lt;=y 如果 x 小於、等於 y，则结果为真。<br>x&gt;y 如果 x 大於 y，则结果为真。<br>x&gt;=y 如果 x 大於、等於 y，则结果为真。<br>x==y 如果 x 等於 y，则结果为真。<br>x!=y 如果 x 不等於 y，则结果为真。<br>x~y 如果 x 符合 regular expression y，则结果为真。<br>x!~y 如果 x 不符合 regular expression y，则结果为真。</p>
<p>上面所提到的 x 与 y，如果二者皆是数字则视为数字之间的比较，<br>否则它们会被转换成字串且以字串的形式做比较。两个字串的比较，<br>会先比较第一个字元，然後比较第二个字元，依此类推，直到有不同<br>的地方出现为止。如果两个字串在较短的一个结束之前是相等，则视<br>为长的字串比短的字串大。例如 &#8220;10&#8243; 比 &#8220;9&#8243; 小，&#8221;abc&#8221; 比 &#8220;abcd&#8221; 小。<br>5.4 使用布林运算的Patterns</p>
<p>一个布林(boolean) pattern 是使用布林运算&#8221;或&#8221;(&#8217;||&#8217;)，&#8221;及&#8221;<br>(&#8217;&amp;&amp;&#8217;)，&#8221;反&#8221;(&#8217;!')来组合其它的pattern。<br>例如：</p>
<p>gawk &#8216;/2400/ &amp;&amp; /foo/&#8217; BBS-list<br>gawk &#8216;/2400/ || /foo/&#8217; BBS-list<br>gawk &#8216;! /foo/&#8217; BBS-list<br>第六章 算式(Expression)作为Actions的叙述</p>
<p>算式(Expression) 是gawk程式里面action的基本构成者。<br>6.1 算术运算</p>
<p>gawk 里的算术运算如下所示：</p>
<p>x+y 加<br>x-y 减<br>-x 负<br>+x 正。实际上没有任何影响。<br>x*y 乘<br>x/y 除<br>x%y 求馀数。例如 5%3=2。<br>x^y<br>x**y x 的 y 次方。例如2^3=8。<br>6.2 比较算式与布林算式</p>
<p>比较算式 (comparison expression) 用来比较字串或数字的关系<br>，运算符号与 C 语言相同。表列如下：</p>
<p>x<y<br /> x&lt;=y<br>x&gt;y<br>x&gt;=y<br>x==y<br>x!=y<br>x~y<br>x!~y</p>
<p>比较的结果为真(true)则其值是 1。否则其值是 0。</p>
<p>布林算式(boolean expression)有下面三种：</p>
<p>boolean1 &amp;&amp; boolean2<br>boolean1 || boolean2<br>! boolean<br>6.3 条件算式(Conditional Expressions)</p>
<p>一个条件式算式是一种特别的算式，它含有3个运算元。<br>条件式算式与C语言的相同：</p>
<p>selector ? if-true-exp : if-false-exp</p>
<p>它有3个子算式。第一个子算式selector 首先会被计算。如果是真,<br>则if-true-exp会被计算且它的值变成整个算式的值。否则if-false-<br>exp 会被计算且它的值变成整个算式的值。</p>
<p>例如下面的例子会产生x的绝对值：</p>
<p>x&gt;0 ? x : -x<br>第七章 Actions里面的控制叙述</p>
<p>在 gawk 程式里面，控制叙述诸如 if、while 等控制程式执行的流<br>程。在 gawk 里的控制叙述与 C 的类似。</p>
<p>很多的控制叙述会包括其它的叙述，被包括的叙述称为 body。假<br>如 body 里面包括一个以上的叙述，必须以大括弧 { } 将这些叙述括起<br>来，而各个叙述之间需以换行(newline)或分号隔开。<br>7.1 if 叙述</p>
<p>if (condition) then-body [else else-body]</p>
<p>如果 condition 为真(true)，则执行 then-body，否则执行 else-body。</p>
<p>举一个例子如下：</p>
<p>if (x % 2 == 0)<br>print &#8220;x is even&#8221;<br>else<br>print &#8220;x is odd&#8221;<br>7.2 while 叙述</p>
<p>while (condition)<br>body</p>
<p>while 叙述做的第一件事就是测试 condition。假如 condition 为真则<br>执行 body 的叙述。body 的叙述执行完後，会再测试 condition，假如<br>condition 为真，则 body 会再度被执行。这个过程会一直被重复直到<br>condition 不再是真。如果 condition 第一次测试就是伪(false)，则<br>body 从没有被执行。</p>
<p>下面的例子会印出每个输入记录(record)的前三个栏位。</p>
<p>gawk &#8216;{ i=1<br>while (i &lt;= 3) {<br>print $i<br>i++<br>}<br>}'<br>7.3 do-while 叙述</p>
<p>do<br>body<br>while (condition)</p>
<p>这个 do loop 执行 body 一次，然後只要 condition 是真则会重复执行 body。<br>即使开始时 condition 是伪，body 也会被执行一次。</p>
<p>下面的例子会印出每个输入记录十次。</p>
<p>gawk '{ i= 1<br>do {<br>print $0<br>i++<br>} while (i &lt;= 10)<br>}'<br>7.4 for 叙述</p>
<p>for (initialization; condition; increment)<br>body</p>
<p>此叙述开始时会执行initialization，然後只要 condition是真，它<br>会重复执行body与做increment 。</p>
<p>下面的例子会印出每个输入记录的前三个栏位。</p>
<p>gawk '{ for (i=1; i&lt;=3; i++)<br>print $i<br>}'<br>7.5 break 叙述</p>
<p>break 叙述会跳出包含它的 for、while、do-while 回圈的最内层。</p>
<p>下面的例子会找出任何整数的最小除数，它也会判断是否为质数。</p>
<p>gawk '# find smallest divisor of num<br>{ num=$1<br>for (div=2; div*div &lt;=num; div++)<br>if (num % div == 0)<br>break<br>if (num % div == 0)<br>printf "Smallest divisor of %d is %d\n", num, div<br>else<br>printf "%d is prime\n", num }'<br>7.6 continue 叙述</p>
<p>continue 叙述使用於 for、while、do-while 回圈内部，它会跳<br>过回圈 body 的剩馀部分，使得它立刻进行下一次回圈的执行。</p>
<p>下面的例子会印出 0 至 20 的全部数字，但是 5 并不会被印出。</p>
<p>gawk 'BEGIN {<br>for (x=0; x&lt;=20; x++) {<br>if (x==5)<br>continue<br>printf ("%d",x)<br>}<br>print ""<br>}'<br>7.7 next 叙述、next file 叙述、exit 叙述</p>
<p>next 叙述强迫 gawk 立刻停止处理目前的记录(record)而继续下一<br>个记录。</p>
<p>next file 叙述类似 next。然而，它强迫 gawk 立刻停止处理目前<br>的资料档。</p>
<p>exit 叙述会使得 gawk 程式停止执行而跳出。然而，如果 END 出现<br>，它会去执行 END 的 actions。<br>第八章 内建函式(Built-in Functions)</p>
<p>内建函式是 gawk 内建的函式，可在 gawk 程式的任何地方呼叫内建<br>函式。<br>8.1 数值方面的内建函式</p>
<p>int(x) 求出 x 的整数部份，朝向 0 的方向做舍去。例如：int(3.9)<br>是 3，int(-3.9) 是 -3。<br>sqrt(x) 求出 x 正的平方根值。例 sqrt(4)=2<br>exp(x) 求出 x 的次方。例 exp(2) 即是求 e*e 。<br>log(x) 求出 x 的自然对数。<br>sin(x) 求出 x 的 sine 值，x 是弪度量。<br>cos(x) 求出 x 的 cosine 值，x 是弪度量。<br>atan2(y,x) 求 y/x 的 arctangent 值，所求出的值其单位是弪度量。<br>rand() 得出一个乱数值。此乱数值平均分布在 0 和 1 之间。这个<br>值不会是 0，也不会是 1。<br>每次执行 gawk，rand 开始产生数字从相同点或 seed。<br>srand(x) 设定产生乱数的开始点或 seed 为 x。如果在第二次你设<br>定相同的 seed 值，你将再度得到相同序列的乱数值。<br>如果省略引数 x，例如 srand()，则现在的日期、时间会<br>被当成 seed。这个方法可使得乱数值是真正不可预测的。<br>srand 的传回值(return value)是前次所设定的 seed 值。<br>8.2 字串方面的内建函式</p>
<p>index(in, find)<br>它会在字串 in 里面，寻找字串 find 第一次出现的地方，传回值是<br>字串 find 出现在字串 in 里面的位置。如果在字串 in 里面找不到字<br>串 find，则传回值为 0。<br>例如：<br>print index("peanut","an")<br>会印出 3。</p>
<p>length(string)<br>求出 string 有几个字元。<br>例如：<br>length("abcde")<br>是 5。</p>
<p>match(string,regexp)<br>match 函式会在字串 string 里面，寻找符合 regexp 的最长、最靠<br>左边的子字串。传回值是 regexp 在 string 的开始位置，即 index<br>值。<br>match 函式会设定内在变数 RSTART 等於 index，它也会设定内在变<br>数 RLENGTH 等於符合的字元个数。如果不符合，则会设定 RSTART 为<br>0、RLENGTH 为 -1。</p>
<p>sprintf(format,expression1,...)<br>举 printf 类似，但是 sprintf 并不印出，而是传回字串。<br>例如：<br>sprintf("pi = %.2f (approx.)',22/7)<br>传回的字串为"pi = 3.14 (approx.)"</p>
<p>sub(regexp, replacement,target)<br>在字串 target 里面，寻找符合 regexp 的最长、最靠左边的地方，<br>以字串 replacement 代替最左边的 regexp。<br>例如：<br>str = "water, water, everywhere"<br>sub(/at/, "ith",str)<br>结果字串str会变成<br>"wither, water, everywhere"</p>
<p>gsub(regexp, replacement, target)<br>gsub 与前面的 sub 类似。在字串 target 里面，寻找符合 regexp 的<br>所有地方，以字串 replacement 代替所有的 regexp。<br>例如：<br>str="water, water, everywhere"<br>gsub(/at/, "ith",str)<br>结果字串str会变成<br>'wither, wither, everywhere"</p>
<p>substr(string, start, length)<br>传回字串 string 的子字串，这个子字串的长度为 length 个字元，<br>从第 start 个位置开始。<br>例如：<br>substr("washington",5,3)<br>传回值为"ing"<br>如果 length 没有出现，则传回的子字串是从第 start 个位置开始<br>至结束。<br>例如：<br>substr("washington",5)<br>传回值为"ington"</p>
<p>tolower(string)<br>将字串string的大写字母改为小写字母。<br>例如：<br>tolower("MiXeD cAsE 123")<br>传回值为"mixed case 123"</p>
<p>toupper(string)<br>将字串string的小写字母改为大写字母。<br>例如：<br>toupper("MiXeD cAsE 123")<br>传回值为"MIXED CASE 123"<br>8.3 输入输出的内建函式</p>
<p>close(filename)<br>将输入或输出的档案 filename 关闭。</p>
<p>system(command)<br>此函式允许使用者执行作业系统的指令，执行完毕後将回到 gawk<br>程式。<br>例如：<br>BEGIN {system("ls")}<br>第九章 使用者定义的函式(User-defined Functions)</p>
<p>复杂的 gawk 程式常常可以使用自己定义的函式来简化。呼叫使用<br>者定义的函式与呼叫内建函式的方法一样。<br>9.1 函式定义的格式</p>
<p>函式的定义可以放在 gawk 程式的任何地方。</p>
<p>一个使用者定义的函式其格式如下：</p>
<p>function name (parameter-list) {<br>body-of-function<br>}</p>
<p>name 是所定义的函式之名称。一个正确的函式名称可包括一序列的字<br>母、数字、下标线 (underscores)，但是不可用数字做开头。</p>
<p>parameter-list 是列出函式的全部引数(argument)，各个引数之<br>间以逗点隔开。</p>
<p>body-of-function 包含 gawk 的叙述 (statement)。它是函式定义<br>里最重要的部份，它决定函式实际要做何种事。<br>9.2 函式定义的例子</p>
<p>下面这个例子，会将每个记录的第一个栏位之值的平方与第二个<br>栏位之值的平方加起来。</p>
<p>{print "sum =",SquareSum($1,$2)}<br>function SquareSum(x,y) {<br>sum=x*x+y*y<br>return sum<br>}<br>第十章 □例</p>
<p>这里将列出 gawk 程式的一些例子。</p>
<p>gawk '{if (NF &gt; max) max = NF}<br>END {print max}&#8217;<br>此程式会印出所有输入行之中，栏位的最大个数。</p>
<p>gawk &#8216;length($0) &gt; 80&#8242;<br>此程式会印出一行超过 80 个字元的每一行。此处只有 pattern 被<br>列出，action 是采用内定的 print。</p>
<p>gawk &#8216;NF &gt; 0&#8242;<br>对於拥有至少一个栏位的所有行，此程式皆会印出。这是一个简<br>单的方法，将一个档案里的所有空白行删除。</p>
<p>gawk &#8216;{if (NF &gt; 0) print}&#8217;<br>对於拥有至少一个栏位的所有行，此程式皆会印出。这是一个简<br>单的方法，将一个档案里的所有空白行删除。</p>
<p>gawk &#8216;BEGIN {for (i = 1; i &lt;= 7; i++)<br>print int(101 * rand())}'<br>此程式会印出□围是 0 到 100 之间的 7 个乱数值。</p>
<p>ls -l files | gawk '{x += $4}; END {print "total bytes: " x}'<br>此程式会印出所有指定的档案之bytes数目的总和。</p>
<p>expand file | gawk '{if (x &lt; length()) x = length()}<br>END {print "maximum line length is " x}'<br>此程式会将指定档案里最长一行的长度印出。expand 会将 tab 改<br>成 space，所以是用实际的右边界来做长度的比较。</p>
<p>gawk 'BEGIN {FS = ":"}<br>{print $1 | "sort"}' /etc/passwd<br>此程式会将所有使用者的login名称，依照字母的顺序印出。</p>
<p>gawk '{nlines++}<br>END {print nlines}'<br>此程式会将一个档案的总行数印出。</p>
<p>gawk 'END {print NR}'<br>此程式也会将一个档案的总行数印出，但是计算行数的工作由gawk<br>来做。</p>
<p>gawk '{print NR,$0}'<br>此程式印出档案的内容时，会在每行的最前面印出行号，它的功<br>能与 'cat -n' 类似。<br>第十一章 结论</p>
<p>gawk 对於资料的处理具有很强的功能。它能够以很短的程式完成<br>想要做的事，甚至一或二行的程式就能完成指定的工作。同样的一件<br>工作，以 gawk 程式来写会比用其它程式语言来写短很多。</p>
<p>gawk 是 GNU 所做的 awk，它是公众软体(Public Domain) 可免费使<br>用。<br>(<a href="http://www.fanqiang.com/"><u><font color=#0000ff>http://www.fanqiang.com</font></u></a>)</p>
<p>原文链接：<a href="http://www.phpx.com/happy/top58375.html"><u><font color=#0000ff>http://www.phpx.com/happy/top58375.html</font></u></a> </p>
<img src ="http://www.cppblog.com/megax/aggbug/44176.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/megax/" target="_blank">megax</a> 2008-03-11 14:06 <a href="http://www.cppblog.com/megax/articles/44176.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]DB2 9 管理之服务器管理</title><link>http://www.cppblog.com/megax/articles/44174.html</link><dc:creator>megax</dc:creator><author>megax</author><pubDate>Tue, 11 Mar 2008 06:04:00 GMT</pubDate><guid>http://www.cppblog.com/megax/articles/44174.html</guid><wfw:comment>http://www.cppblog.com/megax/comments/44174.html</wfw:comment><comments>http://www.cppblog.com/megax/articles/44174.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/megax/comments/commentRss/44174.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/megax/services/trackbacks/44174.html</trackback:ping><description><![CDATA[<p>DB2 实例 是一种逻辑上下文，DB2 命令及函数在其中执行。您可将实例视为管理对数据库文件的访问的服务或守护进程。在一台服务器上可定义多个实例。各实例独立于其他实例，也就是说所有实例均可分别管理、操纵及调优。</p>
<p><a id=more-15></a></p>
<div id=pip>
<div class=guanggao>　　<strong>一、DB2 实例</strong>&nbsp;
<p>&nbsp;</p>
<p>　　1、创建及删除实例</p>
<p>　　DB2 实例 是一种逻辑上下文，DB2 命令及函数在其中执行。您可将实例视为管理对数据库文件的访问的服务或守护进程。在一台服务器上可定义多个实例。各实例独立于其他实例，也就是说所有实例均可分别管理、操纵及调优。</p>
<p>　　要在 Windows 中创建实例，只需执行以下命令：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2icrt instance_name</td>
        </tr>
    </tbody>
</table>
<p>　　在 Linux 和 UNIX 中，您必须另外提供一个用户 ID，用以创建 fenced 用户定义的函数和存储过程进程，形式如下：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2icrt -u fenced_user_ID instance_name</td>
        </tr>
    </tbody>
</table>
<p>　　默认情况下，用户定义的函数和存储过程是在 fenced 模式下创建的，因而这些进程运行在与 DB2 引擎不同的地址空间中，也称为系统控制器进程 db2sysc。这为数据库管理器提供了保护，使之免于被用户定义的例程意外地或恶意地破坏。</p>
<p>　　要删除一个实例，首先断开所有数据库连接，然后执行以下命令停止实例：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2idrop -f instance_name</td>
        </tr>
    </tbody>
</table>
<p>　　2、列举、迁移和更新 DB2 实例</p>
<p>　　要列举服务器上存在的 DB2 实例，可使用以下命令：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2ilist</td>
        </tr>
    </tbody>
</table>
<p>　　若您决定转而使用比服务器上安装的 DB2 软件更新的版本，或者需要将 32 位实例迁移为 64 位实例，就需要进行实例迁移。在Windows 上，实例迁移是在必要的迁移过程中隐式完成的。在 Linux 和 UNIX 上，可使用以下命令显式地迁移已有实例：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2imigr instance_name</td>
        </tr>
    </tbody>
</table>
<p>　　在为 DB2 安装修补程序包或补丁时，一旦在服务器上安装好了修补程序包，您就需要更新已有实例，以链接到新的修补程序文件。使用以下命令更新实例：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2iupdt instance_name</td>
        </tr>
    </tbody>
</table>
<p>3、设置 DB2 环境　　恰当地设置 DB2 环境非常重要，这是因为它控制着 DB2 操作和活动的方式。DB2 环境由以下几部分构成：</p>
<p>　　● DB2 配置文件注册库</p>
<p>　　● 操作系统环境变量</p>
<p>　　● DB2 数据库管理器配置参数</p>
<p>　　● DB2 数据库配置参数</p>
<p>　　4、设置配置文件注册库</p>
<p>　　DB2 配置文件注册库是特定于 DB2 的变量，它会影响 DB2 系统的管理、配置与性能。为使 DB2 配置文件注册库的更改生效，您通常需要停止并重启实例。</p>
<p>　　要列举所支持的全部 DB2 配置文件注册库：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2set -lr</td>
        </tr>
    </tbody>
</table>
<p>　　要设置 DB2 配置文件注册库：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2set registry_variable = value</td>
        </tr>
    </tbody>
</table>
<p>　　请注意，在变量名、等号和变量值之间没有空格。下面给出一个将 DB2COMM 注册库变量设置为单一值的示例：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2set DB2COMM=TCPIP</td>
        </tr>
    </tbody>
</table>
<p>　　将 DB2COMM 注册库变量设置为多个值的示例如下：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2set DB2COMM=TCPIP,NPIPE,LOCAL</td>
        </tr>
    </tbody>
</table>
<p>　　要将 DB2 配置文件注册库重置为默认值，只需使用与上面相同的命令即可，但不指定任何值：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2set registry_variable =</td>
        </tr>
    </tbody>
</table>
<p>　　要显示服务器上当前设置的所有 DB2 配置文件注册库，请执行以下命令：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2set -all</td>
        </tr>
    </tbody>
</table>
<p>5、设置系统环境变量　　要了解您当前工作在哪个 DB2 实例中，可运行以下 DB2 命令：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2 get instance</td>
        </tr>
    </tbody>
</table>
<p>　　此命令的输出结果形式如下：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>The current database manager instance is: DB2</td>
        </tr>
    </tbody>
</table>
<p>　　绝大多数 DB2 环境设置都是由 DB2 配置文件注册库控制的。而那些未存储在配置文件注册库中的设置称为操作系统环境变量。设置系统变量的命令将根据您所使用的平台及 UNIX shell 而有所不同。</p>
<p>　　● 在 Windows 中： set DB2INSTANCE=DB2</p>
<p>　　● 在 Linux 和 UNIX 的 Korn shell 中： export DB2INSTANCE=DB2</p>
<p>　　DB2INSTANCE 是一个需要掌握的重要系统变量。它指定当前应用程序的会话或窗口的默认 DB2 实例。一旦设置好该变量，后续的所有 DB2 命令都将在该实例的作用域内执行。</p>
<p>　　6、设置配置参数</p>
<p>　　在 DB2 中，存在两个配置 &#8220;级别&#8221;。在实例(或数据库管理器)级别，您可为该实例配置整个 DB2 环境，这将影响实例中的所有数据库和使用该实例中数据库的所有应用程序。在数据库 级别，您可配置参数，而这些参数将影响到访问特定数据库的所有应用程序的行为。</p>
<p>　　获取 DBMS 或者 DB 的配置参数：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3><font face=Verdana>db2 get database manager configuration<br>db2 get database configuration for database_name</font></td>
        </tr>
    </tbody>
</table>
<p>　　或者(后同)</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3><font face=Verdana>db2 get database manager cfg<br>db2 get database cfg for database_name</font></td>
        </tr>
    </tbody>
</table>
<p>　　更改 DBMS 或者 DB 的配置参数</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3><font face=Verdana>db2 update database manager configuration using parameter new_value<br>db2 update database configuration for database_name using parameter new_value</font></td>
        </tr>
    </tbody>
</table>
<p>7、联机设置配置参数　　绝大多数配置参数均可在实例或数据库保持运行的情况下联机设置。只要可能，对这些联机配置参数的更改默认为立即生效。例如，若更改了 sortheap 的值，所有新的 SQL 请求将使用新值。为显式指定这种立即生效的行为，可将 immediate 关键字附加到 update 命令中：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3><font face=Verdana>db2 update database manager configuration using parameter new_value immediate<br>db2 update database configuration for database_name using parameter new_value immediate</font></td>
        </tr>
    </tbody>
</table>
<p>　　若您选择将此更改延迟至实例重启或数据库激活时，则应指定 deferred 关键字：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3><font face=Verdana>db2 update database manager configuration using parameter new_value deferred<br>db2 update database configuration for database_name using parameter new_value deferred</font></td>
        </tr>
    </tbody>
</table>
<p>　　有时，您可能希望找出已确定并延迟了哪些更改。为显示数据库管理器配置参数的当前值和挂起值，首先进入实例，然后在 get database manager configuration 命令中指定 show detail 选项，方法如下(请注意，instance_name 是系统环境变量 DB2INSTANCE 设置的值)：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3><font face=Verdana>db2 attach to instance_name<br>db2 get database manager configuration show detail</font></td>
        </tr>
    </tbody>
</table>
<p>　　同样地，要列举数据库配置参数的当前值和挂起值，首先连接到数据库，然后使用 show detail 选项：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3><font face=Verdana>db2 connect to database_name<br>db2 get database configuration for database_name show detail</font></td>
        </tr>
    </tbody>
</table>
<p>　　8、强制停止实例和数据库</p>
<p>　　如果您需要使数据库或数据库管理器配置更改立即生效，而您所更改的参数并非动态，那么就需要停止并重启数据库或整个实例。若存在连接并使用此实例中一个或多个数据库的应用程序，您就无法停止并重启数据库或实例。此时，您可使用如下 DB2 命令，强行使用户断开 与数据库的连接：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2 force application all</td>
        </tr>
    </tbody>
</table>
<p>　　您也可以在停止实例的同时断开所有用户的连接，命令如下：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2stop force</td>
        </tr>
    </tbody>
</table>
<p>　　若您只希望强制停止一个特定的应用程序，则需要了解该应用程序的句柄。 使用以下命令查找句柄：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2 list applications</td>
        </tr>
    </tbody>
</table>
<p>　　强制停止该应用程序的连接，可使用如下 DB2 命令：(x 为该应用程序句柄)</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2 force application (x)</td>
        </tr>
    </tbody>
</table>
<p>　<strong>二、DB2 客户机/服务器连通性</strong>　　1、DB2 客户机/服务器环境</p>
<p>　　由于 DB2 用户间整体通信协议使用情况发生了变化，因此为实现 DB2 客户机/服务器连通性，</p>
<p>　　DB2 目前支持以下协议：</p>
<p>　　● TCP/IP</p>
<p>　　● NPIPE</p>
<p>　　对于到主数据库(如 DB2 for z/OS 和/或 DB2 for iSeries)的连接，必须具备使用 Distributed Relational Database Architecture(DRDA)的 DB2 Connect。</p>
<p>　　2、为远程应用程序连接准备您的 DB2 数据库</p>
<p>　　在 DB2 客户机(应用程序)能够连接到数据库之前，您必须确保服务器端通信得到了恰当的设置，可接收连接请求。要为 TCP/IP 连接准备服务器，您需要设置一个 TCP/IP 监听器，方法如下。</p>
<p>　　(1)、 使用以下命令设置 DB2 配置文件注册库 DB2COMM，使实例能够监听 TCP/IP 的连接：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2set DB2COMM=TCPIP</td>
        </tr>
    </tbody>
</table>
<p>　　(2)、使用正确的端口号更新数据库管理器配置参数 svcename，如下所示：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2 update database manager configuration using svcename 50000</td>
        </tr>
    </tbody>
</table>
<p>　　(3)、数据库管理器配置参数 svcename 并非动态，因此您必须停止并重启实例，以使 TCP/IP 监听器启动，如下所示：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3><font face=Verdana>db2stop<br>db2start</font></td>
        </tr>
    </tbody>
</table>
<p>　　3、使用 DB2 Configuration Assistant</p>
<p>　　DB2 Configuration Assistant 提供了用户友好的向导和图形化界面，可配置您或您的应用程序将使用的环境。通过 Configuration Assistant，您可以：</p>
<p>　　● 添加一个新的数据库连接</p>
<p>　　● 更新数据库连通性信息</p>
<p>　　● 查看并更新数据库管理器配置参数</p>
<p>　　● 查看并更新 DB2 配置文件注册库</p>
<p>　　● 将应用程序绑定到数据库</p>
<p>　　● 更新 Call Level Interface(CLI)设置</p>
<p>　4、配置数据库连通性的三种方法</p>
<p>　　在 DB2 Configuration Assistant 中，有三个选项可用于设置数据库连接。您可以：</p>
<p>　　● 为 DB2 数据库搜索网络</p>
<p>　　● 使用 DB2 访问配置文件</p>
<p>　　● 手动配置连接</p>
<p>　　5、通过搜索网络自动配置数据库连通性</p>
<p>　　DB2 Discovery 搜索并定位您的网络上的 DB2 服务器，您可以选择使用搜索 或已知 发现方法。</p>
<p>　　搜索方法将在网络中搜索任意 DB2 服务器。这种方法需要花上一些时间才能返回结果。</p>
<p>　　如果您知道一些关于希望定位的 DB2 服务器的信息，则可使用已知方法，并提供数据库或服务器名称之类的信息来约束搜索。</p>
<p>　　DB2 允许某些 DB2 服务器、实例或数据库可以被发现或者不被发现。</p>
<p>　　仅在 DB2 服务器上运行 Administration Server(DAS)服务、且 discover 配置参数被设置为 search 时，该 DB2 服务器才可被搜索到，如下所示：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3><font face=Verdana>db2admin start<br>db2 update admin configuration using discover search</font></td>
        </tr>
    </tbody>
</table>
<p>　　您还可控制哪些实例是可被发现的，只需设置 discover_inst 数据库管理器配置参数即可，如下所示：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2 update database manager configuration using discover_inst enable</td>
        </tr>
    </tbody>
</table>
<p>　　各数据库都拥有一个相似的配置参数 —— discover_db，它可启用或禁用数据库发现，如下所示：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2 update database configuration for database_name using discover_db enable</td>
        </tr>
    </tbody>
</table>
<p>　　这里要重点指出，在 DAS、实例或数据库级别禁用发现不会限制 DB2 客户机通过其他方法设置数据库连通性(下文将详细讨论)。DB2 客户机仍然可以连接到远程数据库 —— 即便其数据库配置 discover_db 被禁用也是如此。</p>
<p>　6、使用 DB2 访问配置文件自动配置数据库连通性</p>
<p>　　如果您要为 1,000 台或更多的工作站设置 DB2 客户机/服务器连通性，那么您会怎么做?您当然可以前往每一台工作站，使用Configuration Assistant 中的发现方法，但可能要花上很长一段时间才能完成这个任务。在此类情况下，您应考虑使用 DB2 访问配置文件。</p>
<p>　　访问配置文件中包含客户机配置与 DB2 服务器的连通性时所必需的信息。访问配置文件有两种类型：</p>
<p>　　● 服务器访问配置文件 是在 DB2 服务器上生成的。它包含服务器上定义的全部或选定的部分实例和数据库的相关信息。</p>
<p>　　● 客户机配置文件 是在 DB2 客户机上生成的。它包含客户机上已编目的实例(也称为节点)和数据库的相关信息。</p>
<p>　　让我们逐步地看一下 DB2 访问配置文件方法。</p>
<p>　　(1)、使用 Configuration Assistant 将信息导出到访问配置文件(该文件就是一个 ASCII 文件)。</p>
<p>　　(2)、将导出的文件发送给客户机。</p>
<p>　　(3)、在客户机上使用 Configuration Assistant 将文件导入 DB2 客户机。</p>
<p>　　第三个步骤也可以使用命令实现：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2cfimp access_profile_name</td>
        </tr>
    </tbody>
</table>
<p>　　7、手动配置数据库连通性</p>
<p>　　如果您了解配置连通性所必需的所有信息，那么可以使用 Configuration Assistant 中的 Add Database 向导。</p>
<p>　　(1)、必须首先编目节点(或 DB2 服务器)与实例的结合。</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3><font face=Verdana>db2 catalog tcpip node mynode remote db2server.mycompany.com server db2icdb<br>db2 catalog netbios node jeremy remote N01FCBE3 adapter 0</font></td>
        </tr>
    </tbody>
</table>
<p>　　(2)、编目数据库</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3><font face=Verdana>db2 catalog database sample as mysamp at node mynode<br>db2 catalog database baydb as newbaydb at node mynode</font></td>
        </tr>
    </tbody>
</table>
<p>　8、列举节点和数据库目录　　要在 node 目录中列举服务器与实例的结合，可使用如下命令：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2 list node directory</td>
        </tr>
    </tbody>
</table>
<p>　　要列举 database 目录，可使用如下命令：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>db2 list database directory</td>
        </tr>
    </tbody>
</table>
<p>　　9、附加到实例并连接到数据库</p>
<p>　　通过编目节点和数据库设置完客户机/服务器连通性后，您可附加到实例以进行实例级管理任务，也可连接到数据库以读取该数据库中的数据或向数据库写入数据。</p>
<p>　　要附加到 DB2 实例，可使用 DB2 命令 attach，如下所示：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>attach to nodename user username using password</td>
        </tr>
    </tbody>
</table>
<p>　　附加到实例后，您可在该实例上执行管理任务，例如：</p>
<p>　　● 创建和删除数据库</p>
<p>　　● 检索、更新和重置数据库管理器及数据库配置参数</p>
<p>　　● 管理数据库监控程序</p>
<p>　　● 备份、还原和前滚数据库</p>
<p>　　● 强制用户和应用程序与实例中定义的数据库断开连接</p>
<p>　　要连接到数据库，以选择、插入、更新或删除数据，您必须首先通过以下方式连接到数据库：</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3><font face=Verdana>connect to database_name user username using password<br>[new new_password confirm new_password ]</font></td>
        </tr>
    </tbody>
</table>
<p>　　连接到数据库之后，就可以进行数据库的相应操作了。</p>
</div>
</div>
<img src ="http://www.cppblog.com/megax/aggbug/44174.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/megax/" target="_blank">megax</a> 2008-03-11 14:04 <a href="http://www.cppblog.com/megax/articles/44174.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>