2006年08月07日

 

<%
‘dim conn
dim connstr
dim connType,dbPath

connType=1
Set conn= Server.CreateObject("ADODB.Connection")

IF conn.State = 0 Then
 IF connType= 1 Then
  connstr = "Provider=SQLOLEDB;uid=shadow;pwd=XXXXXX;Initial Catalog=XXXXXX;server=(local);"
 Else
  dbPath = Server.Mappath("\") & "\hkcn\database\webhkcn.mdb"
  connstr = "Provider=Microsoft.JET.OLEDB.4.0;Data Source="& dbPath &";"
 End If
 conn.Open connstr
End If

Function SQLExecute(SqlStr)
 on error resume next
 Dim Rs
 Set Rs=Server.CreateObject("Adodb.Recordset")
 Rs.open SqlStr,conn,1,3
 Set SQLExecute=Rs
 If Err.Number <> 0 Then
  Response.Write("<font color=red>抱歉你在访问本页时出现一个错误以下是错误的详细信息。<br>")
  Response.Write("错误号:"&CStr(Hex(Err.Number))&"<br>")
  Response.Write("错误对象:"&Err.Source&"<br>")
  Response.Write("有关错误的详细描述:"&Err.Description&"<br>")
  Response.Write("如果你始终无法访问本页请联系管理员。")
 End If
End Function
‘=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
%>

<%
‘=================================================
‘ Public Function
‘ Programmer by Jiang Jian(Shadow)
‘ Email:vbcc@sohu.com
‘ Date: 2003-05-26
‘=================================================

‘>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
‘判断用户是否登录
‘>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Function ChkLogin(UserName,Pass)
 Dim Sql,Rs
 Sql="Select id,username,password FROM member WHERE username=’"&UserName&"’ And password=’"&Pass&"’"
 Set Rs=SQLExecute(Sql)
 If Not (Rs.bof or Rs.eof) Then
  ChkLogin=Rs("ID")
 Else
  ChkLogin=False
 End If
 Rs.Close
 Set Rs=Nothing
End Function

‘>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
‘判断是否非法提交数据 True 为正常 False 为非法提交
‘>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Function ChkPost()
 Dim server_v1,server_v2
 Chkpost=False
 server_v1=Cstr(Request.ServerVariables("HTTP_REFERER"))
 server_v2=Cstr(Request.ServerVariables("SERVER_NAME"))
 If Mid(server_v1,8,Len(server_v2))<>server_v2 Then
  Chkpost=False
 Else
  Chkpost=True
 End if
End function

‘====================================================
‘判断用户名是否包含非法字符 True 合法的字符串
‘====================================================
Function CheckString(Str1)
 Dim N
 Dim S
 For N = 1 To Len(Str1)
  S = Asc(Mid(Str1, N))
  If S > 47 And S < 58 Or S > 64 And S < 91 Or S > 96 And S < 122 Or S = 95 Then ‘合法的字符串
   CheckString=True
  Else 
   CheckString=False
  End If
 Next
End Function

‘====================================================
‘判断字符是否为中文 True 合法 False 非法
‘====================================================
Function IsChinese(Str)
 Dim N
 Dim S
 For N = 1 To Len(Str)
  S = Asc(Mid(Str, N))
  If S => 0  Then   
   IsChinese=False
   Exit for
  Else
   IsChinese=True
  End If
 Next
End Function

‘>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
‘判断是否为合法的电话号码 True 合法 False 非法
‘>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Function IsPhone(Str)
 Dim strArray
 IsPhone=False
 strArray=Split(Str,"-",-1,1)
 IF Ubound(strArray)> 0 Then
  IF Len(strArray(0))>2 And Len(strArray(0))< 5 Then
   IF Len(strArray(1))>6 And Len(strArray(1))< 9 Then
    If IsNumeric(strArray(0))=True And  IsNumeric(strArray(1)) Then
     IsPhone=True
    End If
   End If
  End If
 End IF
End Function
 
‘>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
‘判断是否为合法的电子邮件地址 True 合法 False 非法
‘>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Function IsValidEmail(Email)
 Dim Names, name, i, c
 IsValidEmail = True
 Names = Split(Email, "@")
 
 If UBound(Names) <> 1 Then
  IsValidEmail = False
  Exit function
 End If
  
 For Each Name IN Names
  If Len(name) <= 0 Then
   IsValidEmail = False
   Exit Function
  End If
  For i = 1 To Len(name)
   c = Lcase(Mid(name, i, 1))
   If InStr("abcdefghijklmnopqrstuvwxyz_-.", c) <= 0 And Not IsNumeric(c) Then
    IsValidEmail = False
    Exit Function
   End If
  Next
  If Left(name, 1) = "." or Right(name, 1) = "." Then
   IsValidEmail = False
   Exit Function
   End If
  Next
  
 If InStr(names(1), ".") <= 0 Then
  IsValidEmail = False
  Exit Function
 End If
 
 i = Len(names(1)) – InStrRev(names(1), ".")
 If i <> 2 And i <> 3 Then
  IsValidEmail = False
  Exit Function
 End If
 
 If InStr(Email, "..") > 0 Then
  IsValidEmail = False
 End If
End function

‘>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
‘数据分页显示 strUrl 设置成自己本页
‘>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Function PageSplit(objRs,strUrl,cssClass,listSize,cssSep)
 Dim pgnum,page
 page=Request("page")
 objRs.PageSize = listSize
 pgnum=objRs.Pagecount
 if page="" or clng(page)<1 then page=1
 if clng(page) > pgnum then page=pgnum
 if pgnum>0 then objRs.AbsolutePage=page
 If page=1 Then
  Response.Write " 首 页 | 上一页 | "
 Else
  Response.Write " <a class="& cssClass &" href="&strUrl&"page=1>首 页</a><span class="& cssSep &"> | </span>"
  Response.Write "<a class="& cssClass &" href="&strUrl&"page="&page-1&"> 上一页</a><span class="& cssSep &"> | </span>"
 End if
 If objRs.pagecount-page<1 Then
  Response.Write "下一页 | 尾 页"
 Else
  Response.Write "<a class="& cssClass &" href="&strUrl&"page="&page+1&">下一页</a><span class="& cssSep &"> | </span>"
  Response.Write "<a class="& cssClass &" href="&strUrl&"page="&objRs.pagecount&">尾 页</a>"
 End if
 Response.Write "              第 "&page&" 页/共 "&pgnum&" 页"
End Function

‘>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
‘文章分页显示 strUrl 设置成自己本页
‘>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Public Function SplitPage(strContents)
 Dim Page,PageArray
 PageArray=SepPosition(strContents)
 Page=Request("page")
 pgnum=UBound(PageArray)
 IF page="" or clng(page)<0 Then page=0
 IF Clng(page) > pgnum Then page=pgnum
 
 IF pgnum = 0 Then ‘只有一页
  SplitPage=strContents
  Exit Function
 End IF
 
 If Page = 0 Then
  SplitPage=Mid(strContents,1,PageArray(page)-1)
 ElseIf Clng(Page)=pgnum Then
  SplitPage=Mid(strContents,PageArray(page-1)+19,Len(strContents))
 Else
  SplitPage=Mid(strContents,PageArray(page-1)+19,PageArray(page)-(PageArray(page-1)+19))
 End if
End Function

Public Function NavPage(strPage)
 Page=Request("page")
 IF page="" or clng(page)<0 Then page=0
 IF pgnum > 0 Then
  IF Page = 0 Then
   Response.Write "<a class=""SepPage"" href="""&strPage&"&page=" & page & """>上一页</a> "
  Else
   Response.Write "<a class=""SepPage"" href="""&strPage&"&page=" & page – 1 & """>上一页</a> "
  End if
  
  If pgnum-Clng(Page)<1  Then
   Response.Write "<a class=""SepPage"" href="""&strPage&"&page=" & page &""">下一页</a> "
  Else
   Response.Write "<a class=""SepPage"" href="""&strPage&"&page=" & page + 1 & """>下一页</a>"
  End If
  Response.Write "<span class=""I""> 共 " & pgnum + 1 & " 页 当前第 " & page + 1 & " 页</span>"
 End IF
End Function

Public Function SepPosition(strContents)
 Dim intPos,strPos
 Dim intPageArray,strTemp
 strTemp = "[PAGE]——[/PAGE]"
 intPos=Instr(strContents,strTemp)
  strPos = intPos
 Do While (intPos)
  intPos=Instr(intPos+19,strContents,strTemp) 
  strPos=strPos & "," & intPos
 Loop
 SepPosition=Split(strPos,",")
End Function

‘>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
‘截取一定数量的文字输出
‘>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Public Function OutText(strText,intOutSize)
 IF Len(strText)>intOutSize Then
  OutText = Left(strText,intOutSize-3) & "…"
 Else
  OutText = strText
 End If
End Function
%>

 

2006年07月24日

原理,就是象java一样使用preparestatement.
下面例子连接的是sql server数据库
代码如下:
PrepareSql.asp
<%
‘ 定义数据库操作常量
 Const adStateClosed = 0
 Const adOpenForwardOnly = 0, adOpenKeyset = 1, adOpenDynamic = 2, adOpenStatic = 3
 Const adLockReadOnly = 1, adLockPessimistic = 2, adLockOptimistic = 3, adLockBatchOptimistic = 4
 Const adCmdText = 1, adCmdTable = 2, adCmdStoredProc = 4, adExecuteNoRecords = 128
 Const adBigInt = 20, adBoolean = 11, adChar = 129, adDate = 7, adInteger = 3, adSmallInt = 2, adTinyInt = 16, adVarChar = 200
 const adParamInput = 1, adParamOutput = 2, adParamInputOutput = 3, adParamReturnValue = 4
%>
<%Class PrepareSQL
 Private cmdPrep
 Private m_String
 Private m_Sql
 Private m_conn
 public function setconn(conn)
  set m_conn=conn
 end function
 Public Function prepare(sql)
  set cmdPrep=nothing
     SET cmdPrep=Server.CreateObject("ADODB.Command")
  set cmdPrep.ActiveConnection=m_conn
  cmdPrep.CommandText =sql
 End Function
 Public Function setInt(theValue ) 
  cmdPrep.Parameters.Append cmdPrep.CreateParameter("", adInteger, adParamInput,, theValue) 
 End Function
 Public Function setDate(theValue ) 
    cmdPrep.Parameters.Append cmdPrep.CreateParameter("", adVarChar, adParamInput, 100, theValue) 
 End Function
 Public Function setBoolean(theValue ) 
  cmdPrep.Parameters.Append cmdPrep.CreateParameter("", adBoolean, adParamInput, 1, theValue)  
 End Function 
 Public Function setString(theValue ) 
  if(len(theValue)=0 )then
  
  cmdPrep.Parameters.Append cmdPrep.CreateParameter("", adVarChar, adParamInput, 1, theValue)
  else
  cmdPrep.Parameters.Append cmdPrep.CreateParameter("", adVarChar, adParamInput, lenb(theValue), theValue)
  end if
 End Function
 Public Function execute()
  set execute=cmdPrep.Execute
 End Function
End Class%>

test.asp
<!–#include file="../include/datastore.asp"–>
<!–#include file="../include/PrepareSql.asp"–>
<%
Dim ps
Dim cn
set cn=server.CreateObject("adodb.connection")
Dim strcn
strCn="driver={SQL server};server=127.0.0.1;uid=sa;pwd=test;database=PUBS"
cn.Open strCn
set ps=new  PrepareSql 
ps.setconn cn
ps.prepare "select * from user where id =?"
ps.setint 1
dim rs
set rs=ps.execute
%> 

2006年07月19日

第一章。指针的概念

指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。

要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的 类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区。让 我们分别说明。
先声明几个指针放着做例子:
例一:
(1)int *ptr;
(2)char *ptr;
(3)int **ptr;
(4)int (*ptr)[3];
(5)int *(*ptr)[4];
如果看不懂后几个例子的话,请参阅我前段时间贴出的文?lt;<如何理解c和c
++的复杂类型声明>>。

1。 指针的类型。
从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针本身所具有的类型。让我们看看例一中各个指针的 类型:
(1)int *ptr; //指针的类型是int *
(2)char *ptr; //指针的类型是char *
(3)int **ptr; //指针的类型是 int **
(4)int (*ptr)[3]; //指针的类型是 int(*)[3]
(5)int *(*ptr)[4]; //指针的类型是 int *(*)[4]
怎么样?找出指针的类型的方法是不是很简单?

2。指针所指向的类型。
当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译 器将把那片内存区里的内容当做什么来看待。
从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声明符 *去掉,剩下的就是指针所指向的类型。例如:
(1)int *ptr; //指针所指向的类型是int
(2)char *ptr; //指针所指向的的类型是char
(3)int **ptr; //指针所指向的的类型是 int *
(4)int (*ptr)[3]; //指针所指向的的类型是 int()[3]
(5)int *(*ptr)[4]; //指针所指向的的类型是 int *()[4]
在指针的算术运算中,指针所指向的类型有很大的作用。
指针的类型(即指针本身的类型)和指针所指向的类型是两个概念。当你对C越 来越熟悉时,你会发现,把与指针搅和在一起的"类型"这个概念分成"指针的 类型"和"指针所指向的类型"两个概念,是精通指针的关键点之一。我看了不 少书,发现有些写得差的书中,就把指针的这两个概念搅在一起了,所以看起书来前后矛盾,越看越糊涂。

3。 指针的值,或者叫指针所指向的内存区或地址。
指针的值是指针本身存储的数值,这个值将被编译器当作一个地址,而不是一个一般的数值。在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长。
指针所指向的内存区就是从指针的值所代表的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区。以后,我们说一个指针的值是XX,就相当于说该指针指向了以XX为首地址的一片内存区域;我们说一个指针指向了某块
内存区域,就相当于说该指针的值是这块内存区域的首地址。
指针所指向的内存区和指针所指向的类型是两个完全不同的概念。在例一中,指针所指向的类型已经有了,但由于指针还未初始化,所以它所指向的内存区是不存在的,或者说是无意义的。
以后,每遇到一个指针,都应该问问:这个指针的类型是什么?指针指向的类型是什么?该指针指向了哪里?
4。 指针本身所占据的内存区。
指针本身占了多大的内存?你只要用函数sizeof(指针的类型)测一下就知道了。在32位平台里,指针本身占据了4个字节的长度。
指针本身占据的内存这个概念在判断一个指针表达式是否是左值时很有用。

第二章。指针的算术运算

指针可以加上或减去一个整数。指针的这种运算的意义和通常的数值的加减运算的意义是不一样的。例如:
例二:
1。 char a[20];
2。 int *ptr=a;


3。 ptr++;
在上例中,指针ptr的类型是int*,它指向的类型是int,它被初始化为指向整 形变量a。接下来的第3句中,指针ptr被加了1,编译器是这样处理的:它把指针ptr的值加上了sizeof(int),在32位程序中,是被加上了4。由于地址是用字节做单位的,故ptr所指向的地址由原来的变量a的地址向高地址方向增加了4个字节。
由于char类型的长度是一个字节,所以,原来ptr是指向数组a的第0号单元开始的四个字节,此时指向了数组a中从第4号单元开始的四个字节。
我们可以用一个指针和一个循环来遍历一个数组,看例子:
例三:
int array[20];
int *ptr=array;

//此处略去为整型数组赋值的代码。

for(i=0;i<20;i++)
{
(*ptr)++;
ptr++;
}
这个例子将整型数组中各个单元的值加1。由于每次循环都将指针ptr加1,所
以每次循环都能访问数组的下一个单元。
再看例子:
例四:
1。 char a[20];
2。 int *ptr=a;


3。 ptr+=5;
在这个例子中,ptr被加上了5,编译器是这样处理的:将指针ptr的值加上5 乘sizeof(int),在32位程序中就是加上了5乘4=20。由于地址的单位是字节,故现在的ptr所指向的地址比起加5后的ptr所指向的地址来说,向高地址方向移动了20个字节。在这个例子中,没加5前的ptr指向数组a的第0号单元开始的四个字节,加5后,ptr已经指向了数组a的合法范围之外了。虽然这种情况在应用上会出问题,但在语法上却是可以的。这也体现出了指针的灵活性。
如果上例中,ptr是被减去5,那么处理过程大同小异,只不过ptr的值是被减去5乘sizeof(int),新的ptr指向的地址将比原来的ptr所指向的地址向低地址方向移动了20个字节。

总结一下,一个指针ptrold加上一个整数n后,结果是一个新的指针ptrnew,ptrnew的类型和ptrold的类型相同,ptrnew所指向的类型和ptrold所指向的类型也相同。ptrnew的值将比ptrold的值增加了n乘sizeof(ptrold所指向的类型)个字节。就是说,ptrnew所指向的内存区将比ptrold所指向的内存区向高地址方向移动了n乘sizeof(ptrold所指向的类型)个字节。
一个指针ptrold减去一个整数n后,结果是一个新的指针ptrnew,ptrnew的类型和ptrold的类型相同,ptrnew所指向的类型和ptrold所指向的类型也相同。ptrnew的值将比ptrold的值减少了n乘sizeof(ptrold所指向的类型)个字节,就是说,ptrnew所指向的内存区将比ptrold所指向的内存区向低地址方向移动了n乘sizeof(ptrold所指向的类型)个字节。

第三章。运算?amp;和*

这里&是取地址运算符,*是…书上叫做"间接运算符"。
&a的运算结果是一个指针,指针的类型是a的类型加个*,指针所指向的类型是a的类型,指针所指向的地址嘛,那就是a的地址。
*p的运算结果就五花八门了。总之*p的结果是p所指向的东西,这个东西有这些特点:它的类型是p指向的类型,它所占用的地址是p所指向的地址。
例五:
int a=12;
int b;
int *p;
int **ptr;
p=&a;//&a的结果是一个指针,类型是int*,指向的类型是int,指向的地址 是a的地址。
*p=24;//*p的结果,在这里它的类型是int,它所占用的地址是p所指向的地 址,显然,*p就是变量a。
ptr=&p;//&p的结果是个指针,该指针的类型是p的类型加个*,在这里是int
**。该指针所指向的类型是p的类型,这里是int*。该指针所指向的地址就是指针p自己的地址。
*ptr=&b;//*ptr是个指针,&b的结果也是个指针,且这两个指针的类型和所 指向的类型是一样的,所以用&b来给*ptr赋值就是毫无问题的了。
**ptr=34;//*ptr的结果是ptr所指向的东西,在这里是一个指针,对这个指
针再做一次*运算,结果就是一个int类型的变量。

第四章。指针表达式。

一个表达式的最后结果如果是一个指针,那么这个表达式就叫指针表达式。
下面是一些指针表达式的例子:
例六:
int a,b;
int array[10];
int *pa;
pa=&a;//&a是一个指针表达式。
int **ptr=&pa;//&pa也是一个指针表达式。
*ptr=&b;//*ptr和&b都是指针表达式。
pa=array;
pa++;//这也是指针表达式。
例七:
char *arr[20];
char **parr=arr;//如果把arr看作指针的话,arr也是指针表达式
char *str;
str=*parr;//*parr是指针表达式
str=*(parr+1);//*(parr+1)是指针表达式
str=*(parr+2);//*(parr+2)是指针表达式

由于指针表达式的结果是一个指针,所以指针表达式也具有指针所具有的四个要素:指针的类型,指针所指向的类型,指针指向的内存区,指针自身占据的内存。
好了,当一个指针表达式的结果指针已经明确地具有了指针自身占据的内存的话,这个指针表达式就是一个左值,否则就不是一个左值。
在例七中,&a不是一个左值,因为它还没有占据明确的内存。*ptr是一个左值,因为*ptr这个指针已经占据了内存,其实*ptr就是指针pa,既然pa已经在内存中有了自己的位置,那么*ptr当然也有了自己的位置。

第五章。数组和指针的关系

如果对声明数组的语句不太明白的话,请参阅我前段时间贴出的文?lt;<如何理解c和c++的复杂类型声明>>。
数组的数组名其实可以看作一个指针。看下例:
例八:
int array[10]={0,1,2,3,4,5,6,7,8,9},value;


value=array[0];//也可写成:value=*array;
value=array[3];//也可写成:value=*(array+3);
value=array[4];//也可写成:value=*(array+4);
上例中,一般而言数组名array代表数组本身,类型是int [10],但如果把a
rray看做指针的话,它指向数组的第0个单元,类型是int *,所指向的类型是数组单元的类型即int。因此*array等于0就一点也不奇怪了。同理,array+3是一个指向数组第3个单元的指针,所以*(array+3)等于3。其它依此类推。
例九:
char *str[3]={
"Hello,this is a sample!",
"Hi,good morning.",
"Hello world"
};
char s[80];
strcpy(s,str[0]);//也可写成strcpy(s,*str);
strcpy(s,str[1]);//也可写成strcpy(s,*(str+1));
strcpy(s,str[2]);//也可写成strcpy(s,*(str+2));
上例中,str是一个三单元的数组,该数组的每个单元都是一个指针,这些指针各指向一个字符串。把指针数组名str当作一个指针的话,它指向数组的第0号单元,它的类型是char**,它指向的类型是char *。
*str也是一个指针,它的类型是char*,它所指向的类型是char,它指向的地址是字符串"Hello,this is a sample!"的第一个字符的地址,即’H’的地址。
str+1也是一个指针,它指向数组的第1号单元,它的类型是char**,它指向的类型是char *。
*(str+1)也是一个指针,它的类型是char*,它所指向的类型是char,它指向"Hi,good morning."的第一个字符’H’,等等。

下面总结一下数组的数组名的问题。声明了一个数组TYPE array[n],则数组名称array就有了两重含义:第一,它代表整个数组,它的类型是TYPE [n];第二,它是一个指针,该指针的类型是TYPE*,该指针指向的类型是TYPE,也就是数组单元的类型,该指针指向的内存区就是数组第0号单元,该指针自己占有单独的内存区,注意它和数组第0号单元占据的内存区是不同的。该指针的值是不能修改的,即类似array++的表达式是错误的。
在不同的表达式中数组名array可以扮演不同的角色。
在表达式sizeof(array)中,数组名array代表数组本身,故这时sizeof函数
测出的是整个数组的大小。
在表达式*array中,array扮演的是指针,因此这个表达式的结果就是数组第0号单元的值。sizeof(*array)测出的是数组单元的大小。
表达式array+n(其中n=0,1,2,….。)中,array扮演的是指针,故arr
ay+n的结果是一个指针,它的类型是TYPE*,它指向的类型是TYPE,它指向数组第n号单元。故sizeof(array+n)测出的是指针类型的大小。
例十:
int array[10];
int (*ptr)[10];
ptr=&array;
上例中ptr是一个指针,它的类型是int (*)[10],他指向的类型是int [10]
,我们用整个数组的首地址来初始化它。在语句ptr=&array中,array代表数组本身。

本节中提到了函数sizeof(),那么我来问一问,sizeof(指针名称)测出的究
竟是指针自身类型的大小呢还是指针所指向的类型的大小?答案是前者。例如:

int (*ptr)[10];
则在32位程序中,有:
sizeof(int(*)[10])==4
sizeof(int [10])==40
sizeof(ptr)==4
实际上,sizeof(对象)测出的都是对象自身的类型的大小,而不是别的什么类型的大小。

第六章。指针和结构类型的关系

可以声明一个指向结构类型对象的指针。
例十一:
struct MyStruct
{
int a;
int b;
int c;
}
MyStruct ss={20,30,40};//声明了结构对象ss,并把ss的三个成员初始
化为20,30和40。
MyStruct *ptr=&ss;//声明了一个指向结构对象ss的指针。它的类型是
MyStruct*,它指向的类型是MyStruct。
int *pstr=(int*)&ss;//声明了一个指向结构对象ss的指针。但是它的
类型和它指向的类型和ptr是不同的。

请问怎样通过指针ptr来访问ss的三个成员变量?
答案:
ptr->a;
ptr->b;
ptr->c;
又请问怎样通过指针pstr来访问ss的三个成员变量?
答案:
*pstr;//访问了ss的成员a。
*(pstr+1);//访问了ss的成员b。
*(pstr+2)//访问了ss的成员c。
呵呵,虽然我在我的MSVC++6.0上调式过上述代码,但是要知道,这样使用p
str来访问结构成员是不正规的,为了说明为什么不正规,让我们看看怎样通过指
针来访问数组的各个单元:
例十二:
int array[3]={35,56,37};
int *pa=array;
通过指针pa访问数组array的三个单元的方法是:
*pa;//访问了第0号单元
*(pa+1);//访问了第1号单元
*(pa+2);//访问了第2号单元
从格式上看倒是与通过指针访问结构成员的不正规方法的格式一样。
所有的C/C++编译器在排列数组的单元时,总是把各个数组单元存放在连续的存储区里,单元和单元之间没有空隙。但在存放结构对象的各个成员时,在某种编译环境下,可能会需要字对齐或双字对齐或者是别的什么对齐,需要在相邻两个成员之间加若干?quot;填充字节",这就导致各个成员之间可能会有若干个字节的空隙。
所以,在例十二中,即使*pstr访问到了结构对象ss的第一个成员变量a,也不能保证*(pstr+1)就一定能访问到结构成员b。因为成员a和成员b之间可能会有若干填充字节,说不定*(pstr+1)就正好访问到了这些填充字节呢。这也证明了指针的灵活性。要是你的目的就是想看看各个结构成员之间到底有没有填充字节,
嘿,这倒是个不错的方法。
通过指针访问结构成员的正确方法应该是象例十二中使用指针ptr的方法。

第七章。指针和函数的关系

可以把一个指针声明成为一个指向函数的指针。
int fun1(char*,int);
int (*pfun1)(char*,int);
pfun1=fun1;
….
….
int a=(*pfun1)("abcdefg",7);//通过函数指针调用函数。
可以把指针作为函数的形参。在函数调用语句中,可以用指针表达式来作为
实参。
例十三:
int fun(char*);
int a;
char str[]="abcdefghijklmn";
a=fun(str);


int fun(char*s)
{
int num=0;
for(int i=0;i
{
num+=*s;s++;
}
return num;
)
这个例子中的函数fun统计一个字符串中各个字符的ASCII码值之和。前面说了,数组的名字也是一个指针。在函数调用中,当把str作为实参传递给形参s后,实际是把str的值传递给了s,s所指向的地址就和str所指向的地址一致,但是str和s各自占用各自的存储空间。在函数体内对s进行自加1运算,并不意味着同时对str进行了自加1运算。

第八章。指针类型转换

当我们初始化一个指针或给一个指针赋值时,赋值号的左边是一个指针,赋值号的右边是一个指针表达式。在我们前面所举的例子中,绝大多数情况下,指针的类型和指针表达式的类型是一样的,指针所指向的类型和指针表达式所指向的类型是一样的。
例十四:
1。 float f=12.3;
2。 float *fptr=&f;
3。 int *p;
在上面的例子中,假如我们想让指针p指向实数f,应该怎么搞?是用下面的语句吗?
p=&f;
不对。因为指针p的类型是int*,它指向的类型是int。表达式&f的结果是一
个指针,指针的类型是float*,它指向的类型是float。两者不一致,直接赋值的方法是不行的。至少在我的MSVC++6.0上,对指针的赋值语句要求赋值号两边的类型一致,所指向的类型也一致,其它的编译器上我没试过,大家可以试试。为了实现我们的目的,需要进行"强制类型转换":
p=(int*)&f; 如果有一个指针p,我们需要把它的类型和所指向的类型改为TYEP*和TYPE,
那么语法格式是:
(TYPE*)p;
这样强制类型转换的结果是一个新指针,该新指针的类型是TYPE*,它指向的类型是TYPE,它指向的地址就是原指针指向的地址。而原来的指针p的一切属性都没有被修改。

一个函数如果使用了指针作为形参,那么在函数调用语句的实参和形参的结合过程中,也会发生指针类型的转换。
例十五:
void fun(char*);
int a=125,b;
fun((char*)&a);


void fun(char*s)
{
char c;
c=*(s+3);*(s+3)=*(s+0);*(s+0)=c;
c=*(s+2);*(s+2)=*(s+1);*(s+1)=c;
}
}
注意这是一个32位程序,故int类型占了四个字节,char类型占一个字节。函数fun的作用是把一个整数的四个字节的顺序来个颠倒。注意到了吗?在函数调用语句中,实参&a的结果是一个指针,它的类型是int *,它指向的类型是int。形参这个指针的类型是char*,它指向的类型是char。这样,在实参和形参的结合过程中,我们必须进行一次从int*类型到char*类型的转换。结合这个例子,我们可以这样来想象编译器进行转换的过程:编译器先构造一个临时指针 char*temp,然后执行temp=(char*)&a,最后再把temp的值传递给s。所以最后的结果是:s的类型是char*,它指向的类型是char,它指向的地址就是a的首地址。

我们已经知道,指针的值就是指针指向的地址,在32位程序中,指针的值其实是一个32位整数。那可不可以把一个整数当作指针的值直接赋给指针呢?就象下面的语句:
unsigned int a;
TYPE *ptr;//TYPE是int,char或结构类型等等类型。


a=20345686;
ptr=20345686;//我们的目的是要使指针ptr指向地址20345686(十进制

ptr=a;//我们的目的是要使指针ptr指向地址20345686(十进制)
编译一下吧。结果发现后面两条语句全是错的。那么我们的目的就不能达到了吗?不,还有办法:
unsigned int a;
TYPE *ptr;//TYPE是int,char或结构类型等等类型。


a=某个数,这个数必须代表一个合法的地址;
ptr=(TYPE*)a;//呵呵,这就可以了。
严格说来这里的(TYPE*)和指针类型转换中的(TYPE*)还不一样。这里的(TYPE*)的意思是把无符号整数a的值当作一个地址来看待。
上面强调了a的值必须代表一个合法的地址,否则的话,在你使用ptr的时候,就会出现非法操作错误。

想想能不能反过来,把指针指向的地址即指针的值当作一个整数取出来。完全可以。下面的例子演示了把一个指针的值当作一个整数取出来,然后再把这个整数当作一个地址赋给一个指针:
例十六:
int a=123,b;
int *ptr=&a;
char *str;
b=(int)ptr;//把指针ptr的值当作一个整数取出来。
str=(char*)b;//把这个整数的值当作一个地址赋给指针str。

好了,现在我们已经知道了,可以把指针的值当作一个整数取出来,也可以把一个整数值当作地址赋给一个指针。

第九章。指针的安全问题

看下面的例子:
例十七:
char s=’a’;
int *ptr;
ptr=(int*)&s;
*ptr=1298;
指针ptr是一个int*类型的指针,它指向的类型是int。它指向的地址就是s的首地址。在32位程序中,s占一个字节,int类型占四个字节。最后一条语句不但改变了s所占的一个字节,还把和s相临的高地址方向的三个字节也改变了。这三个字节是干什么的?只有编译程序知道,而写程序的人是不太可能知道的。也许这三个字节里存储了非常重要的数据,也许这三个字节里正好是程序的一条代码,而由于你对指针的马虎应用,这三个字节的值被改变了!这会造成崩溃性的错误。
让我们再来看一例:
例十八:
1。 char a;
2。 int *ptr=&a;


3。 ptr++;
4。 *ptr=115;
该例子完全可以通过编译,并能执行。但是看到没有?第3句对指针ptr进行自加1运算后,ptr指向了和整形变量a相邻的高地址方向的一块存储区。这块存储区里是什么?我们不知道。有可能它是一个非常重要的数据,甚至可能是一条代码。而第4句竟然往这片存储区里写入一个数据!这是严重的错误。所以在使用指针时,程序员心里必须非常清楚:我的指针究竟指向了哪里。
在用指针访问数组的时候,也要注意不要超出数组的低端和高端界限,否则也会造成类似的错误。
在指针的强制类型转换:ptr1=(TYPE*)ptr2中,如果sizeof(ptr2的类型)大
于sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是安全的。如果sizeof(ptr2的类型)小于sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是不安全的。至于为什么,读者结合例十七来想一想,应该会明白的。

2006年07月18日

最简单的方法:
  1、http://www.python.org/download下载安装好Python;
  2、把python的目录加到你的环境变量path里面,不加也可以,就是每次自己打路径;
  3、http://www.mems-exchange.org/software/files/quixote/下载,解压缩Quixote,文档在doc目录里面;安装Quixote,在Quixote目录里面:python setup.py install。 
  4、在Quixote的server目录里面运行python simple_server.py,访问http://localhost:8080/看看。
  :)

http://wiki.woodpecker.org.cn/moin/PyWebAppFrameworks

2006年07月17日

The reliability and longevity of the C programming language coupled with the stability of MySQL make them a strong pair for system database management. In last month’s MySQL column, I went over the basics of developing a Perl interface to MySQl. Before that, I covered PHP with MySQL. This month, I will discuss building an interface to MySQL with C. As this is primarily a MySQL article, I will gloss over some of the minor aspects of C and assume that the reader understands the basics of C. If you don’t, however, you can find plenty of information in the tutorial section of C/C++ Users Journal magazine.

Connecting to MySQL

The first task in writing a C script to interact with MySQL is to form a connection to MySQL. To do this, we must include a couple of header files. For our purposes, we will use stdio.h, which contains some standard input and output definitions, and mysql.h, which is a header file containing many standard MySQL definitions. These two files come with C and MySQL, respectively; you shouldn’t have to download them from the Web.

   #include <stdio.h>
   #include "/usr/include/mysql/mysql.h"

   /* C to MySQL Program */

   int main(int argc, char *argv[])
   {
           MYSQL mysql;
           MYSQL_RES *result;
           MYSQL_ROW row;

Because of the < and > symbols around stdio.h, C is instructed to look for it in the default location for C header files or in the user’s path. Since mysql.h is not in the default locations on my servers, I used whereis to locate it and then with the aide of doublequotes, specified its exact location for C before compiling my script with the GNU C Compiler (gcc). I also specified the MySQL directory and the location of mysqlclient at compile time:

gcc -o mysql_c_program mysql_c_program.c
   -L/usr/include/mysql -L/usr/lib/mysql -lmysqlclient

[This is to be entered on one line.]

Within the standard main function, the connection to MySQL is established. The first line sets up the definition for MySQL, with the variable mysql. The second line defines and names a result set based on the definitions for MYSQL_RES in mysql.h. The results are to be stored in the array results, which will be an array of rows from MySQL. The third internal line uses the definition for MYSQL_ROW to establish the variable row, which will be an array of columns from MySQL.

After setting up the header files and initial variables, we’re ready to initialize MySQL:

   if(!mysql_init(&mysql))
   {
      fprintf(stderr, "Cannot initialize MySQL");
      exit();
   }

In the if statement here, there’s a reverse maneuver that could confuse beginners to programming. It’s saying, "If we can’t initialize MySQL, then print a message stating that we cannot do it." The function mysql_init() initializes the connection to MySQL using the variable mysql defined at the beginning of the main function. The exclamation point (!) just before the mysql_init() function means "not" or "false". This is the confusing reversal that I mentioned. If C is not able to initialize MySQL, then it is to perform the action contained in the curly braces (the statement block). In this case, it’s instructed to print or fprintf the error message that the server generates and would normally send to the standard error output (i.e., STDERR: either a log or the screen) along with the message contained within quotes here. After printing the error messages, C is to end the program – signified by exit(). If C is successful in initializing MySQL, however, then we can then attempt to establish a connection to MySQL:

   if(!mysql_real_connect(&mysql, "localhost",
      "user", "password", "db1", 0, NULL, 0))
   {
      fprintf(stderr, "%d: %s \n",
         mysql_errno(&mysql), mysql_error(&mysql));
      exit();
   }

The elements of the mysql_real_connect() function here are fairly obvious: name the database type as MySQL (as opposed to PostgreSQL or something else) through the mysql variable, give the host name or IP address, give the user name and password, and specify the database to use. As for the three remaining items, they are the port number, the Unix socket, and the client flag. By giving zeros and NULL, we’re essentially saying to use the defaults for these. Incidentally, we’re using mysql_real_query() here, but we could just as easily use mysql_query(). The main difference between the two is that mysql_real_query will allow the retrieval of binary data, which may not be necessary, but it’s safer to use this function. If the script cannot connect, then it is to print the error message generated by the server (STDERR) along with the MySQL error number (hence the %d format instruction for displaying digits or a number) and then a string (%s) containing the MySQL error message and then a line feed or a new line (\n). The actual values to plug into the format follow, of course, separated by commas.

SQL Statements

If the MySQL connection does not fail, the script can then confidently query the database with the mysql_query() function:

   if(mysql_query(&mysql,
      "SELECT rec_id, col1, col2 FROM table1"))
   {
      fprintf(stderr, "%d:  %s\n",
         mysql_errno(&mysql), mysql_error(&mysql));
   }
   else
   {
      result = mysql_store_result(&mysql);

      while(row = mysql_fetch_row(result))
      {
         printf("%s (%s) - %s \n", row[1], row[0], row[2]);
      }
      mysql_free_result(result);
   }
      mysql_close(&mysql);
   }

Here again, by using mysql_real_query(), we’re using a function designed to handle binary data. If we know for sure that the data does not contain any binary data, then we could use mysql_query() instead. Although the if statement above doesn’t have the negator (i.e., !), it still has an odd twist to its logic. Control statements usually look for the results of 0 or 1 (or something other than 0) to decide how to proceed. If the test criteria or condition returns a value of 1 when executed, then the test is said to have succeeded. Therefore, what is contained in the statement block is to be performed. When an if statement is coupled with an else statement, then if the test returns a 0, the else statement’s block is to be performed:

   if(test)
   {
      execute if test returns 0;
   }
   else
   {
      execute if test returns 1;
   }

This is what one would normally expect from an if statement. What’s odd is that the mysql_real_query() (and mysql_query()) returns 0 if it’s not successful. So in this example, if the SQL statement does not succeed in selecting data from MySQL, then 1 will be returned – which would normally mean success. Therefore, the if statement will print out of an error message. However, if mysql_real_query() is successful, it will return a 0 (normally meaning failure) and then the contents of the else statement will be executed. This is a little awkward. You just need to remember that the results are the opposite for these functions.

As for the instruction within the else statement, the first line captures the results of the mysql_real_query(). That’s the role of mysql_store_result(): to get the results and to store them in an internal buffer temporarily for manipulation. In this case, we’re naming that space in memory, result. Later we free up the buffer when we issue a mysql_free_result() with the variable name in the parenthesis.

Before we let go of the array of data, though, we need to loop through each row of it and display each for the user. We do this with a while statement and the msqyl_fetch_row() function. This function retrieves one row at a time of the results from MySQL and, in this particular script, it stores each row in the variable row. The while statement then prints to the screen the value of each column in the format shown. Note that each column is extracted by typical array syntax (i.e., array[n]). The formatting instructions for the printf are in doublequotes, the same method as with the fprintf in the if statement earlier. Once while has gone through each row of the results, it will stop and then free up the buffer of the data and the else statement will be concluded. We end this brief script with a mysql_close() to finish the MySQL session and disconnect from MySQL. The final closing curly brace, of course, ends the main function.

Adding Data

To change data in MySQL with the C API, we use the mysql_query(). We can employ it either directly with an appropriate SQL statement, or we can use a constant variable and insert it when needed within the parenthesis of mysql_query(). Below is what an UPDATE statement might look like in a C script. Note that I’ve left out the usual MySQL initialization and connection functions, as well as the error message instructions, to save space.

   ...

   const char *sql_update =
      "UPDATE table1 set col1 = 'text'
       WHERE rec_id = '1000'";

   ...   /* MySQL Initialization & Connection */

   if(mysql_query(&mysql, sql_update))
   {
      fprintf(stderr, ...);
      mysql_close(&mysql);
      exit();
   }

   ...

If the mysql_query() is successful in deploying the sql_update, then a 0 will be returned and nothing further will be done. Otherwise, the fprintf will display an error message. If we wanted to give the user some feedback that the UPDATE statement was successful, we could add an else statement that prints a message saying so.

To do an INSERT statement that uses variables instead of the actual values (e.g., ‘text’ or ‘1000′), we would follow the INSERT syntax and just use variable names:

   ...

   const char *sql_insert =
   "INSERT INTO table1 (col1) VALUES (%s)";
   char query[4096];
   const char *colors[] = {"red", "yellow", "blue"};
   uint nbr_colors = sizeof(colors)/sizeof(char *);
   uint x;

   ...   /* MySQL Initialization & Connection */

   for(x = 1; x < nbr_colors; x++)
   {
       sprintf(query, sql_insert, colors[x]);
       if(mysql_query(&mysql, query))
       {
          fprintf(stderr, "Could not insert row. %s %d: \%s \n",
		          query, mysql_errno(&mysql), mysql_error(&mysql));
       mysql_close(&mysql);
       exit();
   }
   printf("Row %d inserted \n", x);

   ...

In the SQL statement sql_insert, we’ve prepared the way with %s to indicate that a string value will be provided later as the column’s value. The next line sets up a character variable with a size of 4096 bytes or four kilobytes. This reserves a temporary buffer that we will use later in our mysql_query(). Next, we create an array containing a list of primary colors that are to be inserted into table1. Following this line, we declare another variable that counts the number of elements in colors. This is unnecessary, of course, because we know that there are three colors. Nevertheless, it may be useful if we were later to modify this script to allow the user to enter a list of colors. In a situation like this, we would not know how many colors or elements the user will enter and would need C to count them. The final variable declaration is for x, which we will use in a for statement later. Note that all of the variables must be declared before initializing MySQL.

In this script excerpt, we’re using a for statement to loop through the array of colors to insert them into the table one at a time. The variable x is set to 0 to start. The test condition is to check whether x is less than the number of colors in the array. Otherwise, the script is to execute the statement block and increment the x counter (x++) by 1 when finishing each loop. With the sprintf statement, we’re able to reuse the INSERT statement. Next, the if statement attempts to execute query. If it’s unable to do so, an error message is given and the session is closed. If the query is accomplished, a message is displayed saying that array element number x was inserted into the table in MySQL.

Conclusion

As you can see, it’s not too hard to get started putting together scripts in C to interface with MySQL. I’ve presented only the basic related functions and options in this article, though. There are many more possibilities with the C API for MySQL. If you would like to learn more about this API, you can read the C API section of MYSQL AB’s manual on their site.

2006年06月22日

  1: 删除LOG
1:分离数据库   企业管理器->服务器->数据库->右键->分离数据库
2:删除LOG文件
3:附加数据库  企业管理器->服务器->数据库->右键->附加数据库
此法生成新的LOG,大小只有520多K
   再将此数据库设置自动收缩
或用代码:
下面的示例分离 77169database,然后将 77169database 中的一个文件附加到当前服务器。

EXEC sp_detach_db @dbname = ‘77169database’
EXEC sp_attach_single_file_db @dbname = ‘77169database’,
   @physname = ‘c:\Program Files\Microsoft SQL Server\MSSQL\Data\77169database.mdf’


2:清空日志
DUMP  TRANSACTION  库名  WITH  NO_LOG    

再:
企业管理器–右键你要压缩的数据库–所有任务–收缩数据库–收缩文件–选择日志文件–在收缩方式里选择收缩至XXM,这里会给出一个允许收缩到的最小M数,直接输入这个数,确定就可以了

3: 如果想以后不让它增长
企业管理器->服务器->数据库->属性->事务日志->将文件增长限制为2M
  


自动收缩日志,也可以用下面这条语句
ALTER DATABASE 数据库名
SET AUTO_SHRINK ON

故障还原模型改为简单,用语句是
USE MASTER
GO
ALTER DATABASE 数据库名 SET RECOVERY SIMPLE
GO
———————————————————————————

截断事务日志:

BACKUP LOG { database_name | @database_name_var }
{
    [ WITH
        { NO_LOG | TRUNCATE_ONLY } ]
}

–压缩日志及数据库文件大小

/*–特别注意
请按步骤进行,未进行前面的步骤,请不要做后面的步骤
否则可能损坏你的数据库.
–*/

1.清空日志
DUMP  TRANSACTION  库名  WITH  NO_LOG    

2.截断事务日志:
BACKUP LOG 数据库名 WITH NO_LOG

3.收缩数据库文件(如果不压缩,数据库的文件不会减小
企业管理器–右键你要压缩的数据库–所有任务–收缩数据库–收缩文件
–选择日志文件–在收缩方式里选择收缩至XXM,这里会给出一个允许收缩到的最小M数,直接输入这个数,确定就可以了
–选择数据文件–在收缩方式里选择收缩至XXM,这里会给出一个允许收缩到的最小M数,直接输入这个数,确定就可以了

也可以用SQL语句来完成
–收缩数据库
DBCC SHRINKDATABASE(客户资料)

–收缩指定数据文件,1是文件号,可以通过这个语句查询到:select * from sysfiles
DBCC SHRINKFILE(1)

4.为了最大化的缩小日志文件(如果是sql 7.0,这步只能在查询分析器中进行)
a.分离数据库:
企业管理器–服务器–数据库–右键–分离数据库

b.在我的电脑中删除LOG文件

c.附加数据库:
企业管理器–服务器–数据库–右键–附加数据库

此法将生成新的LOG,大小只有500多K

或用代码:
下面的示例分离 77169database,然后将 77169database 中的一个文件附加到当前服务器。

a.分离
EXEC sp_detach_db @dbname = ‘77169database’

b.删除日志文件

c.再附加
EXEC sp_attach_single_file_db @dbname = ‘77169database’,
   @physname = ‘c:\Program Files\Microsoft SQL Server\MSSQL\Data\77169database.mdf’

5.为了以后能自动收缩,做如下设置:
企业管理器–服务器–右键数据库–属性–选项–选择"自动收缩"

–SQL语句设置方式:
EXEC sp_dboption ‘数据库名’, ‘autoshrink’, ‘TRUE’

6.如果想以后不让它日志增长得太大
企业管理器–服务器–右键数据库–属性–事务日志
–将文件增长限制为xM(x是你允许的最大数据文件大小)

–SQL语句的设置方式:
alter database 数据库名 modify file(name=逻辑文件名,maxsize=20)
——————————————————————————————-
/*–压缩数据库的通用存储过程

压缩日志及数据库文件大小
因为要对数据库进行分离处理
所以存储过程不能创建在被压缩的数据库中

–邹建 2004.3–*/

/*–调用示例
exec p_compdb ‘test’
–*/

use master  –注意,此存储过程要建在master数据库中
go

if exists (select * from dbo.sysobjects where id = object_id(N’[dbo].[p_compdb]‘) and OBJECTPROPERTY(id, N’IsProcedure’) = 1)
drop procedure [dbo].[p_compdb]
GO

create proc p_compdb
@dbname sysname, –要压缩的数据库名
@bkdatabase bit=1, –因为分离日志的步骤中,可能会损坏数据库,所以你可以选择是否自动数据库
@bkfname nvarchar(260)=” –备份的文件名,如果不指定,自动备份到默认备份目录,备份文件名为:数据库名+日期时间
as
–1.清空日志
exec(‘DUMP TRANSACTION ['+@dbname+'] WITH  NO_LOG’)

–2.截断事务日志:
exec(‘BACKUP LOG ['+@dbname+'] WITH NO_LOG’)

–3.收缩数据库文件(如果不压缩,数据库的文件不会减小
exec(‘DBCC SHRINKDATABASE(['+@dbname+'])’)

–4.设置自动收缩
exec(‘EXEC sp_dboption ”’+@dbname+”’,”autoshrink”,”TRUE”’)

–后面的步骤有一定危险,你可以可以选择是否应该这些步骤
–5.分离数据库
if @bkdatabase=1
begin
if isnull(@bkfname,”)=”
set @bkfname=@dbname+’_'+convert(varchar,getdate(),112)
+replace(convert(varchar,getdate(),108),’:',”)
select 提示信息=’备份数据库到SQL 默认备份目录,备份文件名:’+@bkfname
exec(‘backup database ['+@dbname+'] to disk=”’+@bkfname+””)
end

–进行分离处理
create table #t(fname nvarchar(260),type int)
exec(‘insert into #t select filename,type=status&0×40 from ['+@dbname+']..sysfiles’)
exec(’sp_detach_db ”’+@dbname+””)

–删除日志文件
declare @fname nvarchar(260),@s varchar(8000)
declare tb cursor local for select fname from #t where type=64
open tb
fetch next from tb into @fname
while @@fetch_status=0
begin
set @s=’del "’+rtrim(@fname)+’"’
exec master..xp_cmdshell @s,no_output
fetch next from tb into @fname
end
close tb
deallocate tb

–附加数据库
set @s=”
declare tb cursor local for select fname from #t where type=0
open tb
fetch next from tb into @fname
while @@fetch_status=0
begin
set @s=@s+’,”’+rtrim(@fname)+””
fetch next from tb into @fname
end
close tb
deallocate tb
exec(’sp_attach_single_file_db ”’+@dbname+””+@s)
go

2006年06月16日

SchtasksSchedules commands and programs to run periodically or at a specific time. Adds and removes tasks from the schedule, starts and stops tasks on demand, and displays and changes scheduled tasks.

To view the command syntax, click the following command:

schtasks create

Creates a new scheduled task.

Syntax
schtasks /create /tn TaskName /tr TaskRun /sc schedule [/mo modifier] [/d day] [/m month[,month...] [/i IdleTime] [/st StartTime] [/sd StartDate] [/ed EndDate] [/s computer [/u [domain\]user /p password]] [/ru {[Domain\]User | "System"} [/rp Password]] /?

Parameters
/tn TaskName
Specifies a name for the task.
/tr TaskRun
Specifies the program or command that the task runs. Type the fully qualified path and file name of an executable file, script file, or batch file. If you omit the path, SchTasks.exe assumes that the file is in the Systemroot\System32 directory.
/sc schedule
Specifies the schedule type. Valid values are MINUTE, HOURLY, DAILY, WEEKLY, MONTHLY, ONCE, ONSTART, ONLOGON, ONIDLE. Value Description
MINUTE, HOURLY, DAILY, WEEKLY, MONTHLY Specifies the time unit for the schedule.
ONCE The task runs once at a specified date and time.
ONSTART The task runs every time the system starts. You can specify a start date, or run the task the next time the system starts.
ONLOGON The task runs whenever a user (any user) logs on. You can specify a date, or run the task the next time the user logs on.
ONIDLE The task runs whenever the system is idle for a specified period of time. You can specify a date, or run the task the next time the system is idle.

/mo modifier
Specifies how often the task runs within its schedule type. This parameter is required for a MONTHLY schedule. This parameter is valid, but optional, for a MINUTE, HOURLY, DAILY, or WEEKLY schedule. The default value is 1. Schedule type Modifier Description
MINUTE 1 – 1439 The task runs every n minutes.
HOURLY 1 – 23 The task runs every n hours.
DAILY 1 – 365 The task runs every n days.
WEEKLY 1 – 52 The task runs every n weeks.
MONTHLY 1 – 12 The task runs every n months.
LASTDAY The task runs on the last day of the month.
FIRST, SECOND, THIRD, FOURTH, LAST Use with the /d day parameter to run a task on a particular week and day. For example, on the third Wednesday of the month.

/d day
Specifies a day of the week or a day of a month. Valid only with a WEEKLY or MONTHLY schedule. Schedule type Day values
WEEKLY Optional. Valid values are MON – SUN and * (every day). MON is the default.
MONTHLY A value of MON – SUN is required when the FIRST, SECOND, THIRD, FOURTH, or LAST modifier (/mo) is used. A value of 1 – 31 is optional and is valid only with no modifier or a modifier of the 1 – 12 type. The default is day 1 (the first day of the month).

/m month[,month...]
Specifies a month of the year. Valid values are JAN – DEC and * (every month). The /m parameter is valid only with a MONTHLY schedule. It is required when the LASTDAY modifier is used. Otherwise, it is optional and the default value is * (every month).
/i IdleTime
Specifies how many minutes the computer is idle before the task starts. Type a whole number from 1 to 999. This parameter is valid only with an ONIDLE schedule, and then it is required.
/st StartTime
Specifies the time of day that the task starts in HH:MM:SS 24-hour format. The default value is the current local time when the command completes. The /st parameter is valid with MINUTE, HOURLY, DAILY, WEEKLY, MONTHLY, and ONCE schedules. It is required with a ONCE schedule.
/sd StartDate
Specifies the date that the task starts in MM/DD/YYYY format. The default value is the current date. The /sd parameter is valid with all schedules, and is required for a ONCE schedule.
/ed EndDate
Specifies the last date that the task is scheduled to run. This parameter is optional. It is not valid in a ONCE, ONSTART, ONLOGON, or ONIDLE schedule. By default, schedules have no ending date.
/s Computer
Specifies the name or IP address of a remote computer (with or without backslashes). The default is the local computer.
/u [domain\]user
Runs the command with the permissions of the specified user account. By default, the command runs with the permissions of the user logged on to the computer running SchTasks.
/p password
Specifies the password of the user account specified in the /u parameter. This parameter is required when the /u parameter is used.
/ru {[Domain\]User | "System"}
Runs the tasks with the permission of the specified user account. By default, the task runs with the permissions of the user logged on to the computer running SchTasks. Value Description

[Domain\]User Specifies a user account.
"System" or "" Specifies the NT Authority\System account, which is used by the operating system.

/rp Password
Specifies the password of the user account that is specified in the /ru parameter. If you omit this parameter when specifying a user account, SchTasks.exe prompts you for the password and obscures the text you type. Tasks run with with permissions of the NT Authority\System account do not require a password and SchTasks.exe does not prompt for one.
/?
Displays help at the command prompt.
Remarks
Using the /s, /u, and /p command-line options
The /u and /p command-line options are available only when you use /s. You must use /p with /u to provide the user’s password.

 
SchTasks.exe does not verify program file locations or user account passwords. If you do not enter the correct file location or the correct password for the user account, the task is created, but it does not run. Also, if the password for an account changes or expires, and you do not change the password saved in the task, then the task does not run.
The NT Authority\System account does not have interactive logon rights. Users do not see and cannot interact with programs run with system permissions.
Each task runs only one program. However, you can create a batch file that starts multiple tasks, and then schedule a task that runs the batch file.
You can test a task as soon as you create it. Use the run operation to test the task and then check the SchedLgU.txt file (Systemroot\SchedLgU.txt) for errors.
Syntax and examples for each schedule type
To view the command syntax, click a command:

schtasks create minute

Syntax
schtasks /create /tn TaskName /tr TaskRun /sc minute [/mo {1 - 1439}] [/st StartTime] [/sd StartDate] [/ed EndDate] [/s computer [/u [domain\]user /p password]] [/ru {[Domain\]User | "System"} [/rp Password]]

Example
To schedule a task to run every 20 minutes
The following command schedules a security script, Sec.vbs, to run every 20 minutes. Because the command does not include a starting date or time, the task starts 20 minutes after the command completes, and runs every 20 minutes thereafter whenever the system is running. Notice that the security script source file is located on a remote computer, but that the task is scheduled and executes on the local computer.

schtasks /create /sc minute /mo 20 /tn "Security Script" /tr \\central\data\scripts\sec.vbs

In response, SchTasks.exe displays a message explaining that the task will run with the permissions of the current user and requests the current user’s password. When you enter the password, SchTasks.exe obscures the text you type.


The task will be created under current logged-in user name.
Please enter the password
************

Then, SchTasks.exe displays a message indicating that the task is scheduled:

SUCCESS: The Scheduled Task "Security Script" has successfully been created.
A query shows the task that the command scheduled:


TaskName                  Next Run Time            Status
========================= ======================== ==============
Security Script           10:50:00 AM , 4/4/2001   


schtasks create hourly

Syntax
schtasks /create /tn TaskName /tr TaskRun /sc hourly [/mo {1 - 365}] [/st StartTime] [/sd StartDate] [/ed EndDate] [/s computer [/u [domain\]user /p password]] [/ru {[Domain\]User | "System"} [/rp Password]]

Example
To schedule a command that runs every hour at five minutes past the hour
The following command schedules the MyApp program to run hourly beginning at five minutes past midnight. Because the /mo parameter is omitted, the command uses the default value for the hourly schedule, which is every (1) hour. If this command is issued after 12:05 A.M., the program will not run until the next day.

schtasks /create /sc hourly /st 00:05:00 /tn "My App" /tr c:\apps\myapp.exe

To schedule a command that runs every five hours
The following command schedules the MyApp program to run every five hours beginning on the first day of March 2001. It uses the /mo parameter to specify the interval and the /sd parameter to specify the start date. Because the command does not specify a start time, the current time is used as the start time.

schtasks /create /sc hourly /mo 5 /sd 03/01/2001 /tn "My App" /tr c:\apps\myapp.exe

schtasks create daily

Syntax
schtasks /create /tn TaskName /tr TaskRun /sc daily [/mo {1 - 365}] [/st StartTime] [/sd StartDate] [/ed EndDate] [/s computer [/u [domain\]user /p password]] [/ru {[Domain\]User | "System"} [/rp Password]]

Example
To schedule a task that runs every day
The following example schedules the MyApp program to run once a day, every day, at 8:00 A.M. until December 31, 2001. Because it omits the /mo parameter, the default interval of 1 is used to run the command every day.

schtasks /create /tn "My App" /tr c:\apps\myapp.exe /sc daily /st 08:00:00 /ed 12/31/2001

To schedule a task that runs every other day
The following example schedules the MyApp program to run every other day at 1:00 P.M. (13:00) beginning on December 31, 2001. The command uses the /mo parameter to specify an interval of two (2) days.

schtasks /create /tn "My App" /tr c:\apps\myapp.exe /sc daily /mo 2 /st 13:00:00 /sd 12/31/2001

schtasks create weekly

Syntax
schtasks /create /tn TaskName /tr TaskRun /sc weekly [/d {MON - SUN | *}] [/mo {1 - 52}] [/st StartTime] [/sd StartDate] [/ed EndDate] [/s computer [/u [domain\]user /p password]] [/ru {[Domain\]User | "System"} [/rp Password]]

Example
To schedule a task that runs every six weeks
The following command schedules the MyApp program to run on a remote computer every six weeks. The command uses the /mo parameter to specify the interval. It also uses the /s parameter to specify the remote computer and the /ru parameter to schedule the task to run with the permissions of the user’s Administrator account. Because the /rp parameter is omitted, SchTasks.exe prompts the user for the Administrator account password.

Also, because the command is run remotely, all paths in the command, including the path to MyApp.exe, refer to paths on the remote computer.

schtasks /create /tn "My App" /tr c:\apps\myapp.exe /sc weekly /mo 6 /s Server16 /ru Admin01

To schedule a task that runs every other week on Friday
The following command schedules a task to run every other Friday. It uses the /mo parameter to specify the two-week interval and the /d parameter to specify the day of the week. To schedule a task that runs every Friday, omit the /mo parameter or set it to 1.

schtasks /create /tn "My App" /tr c:\apps\myapp.exe /sc weekly /mo 2 /d FRI

schtasks create monthly

Syntax
General Monthly Schedule Syntax
schtasks /create /tn TaskName /tr TaskRun /sc monthly [/mo {FIRST | SECOND | THIRD | FOURTH | LAST | LASTDAY] [/d {MON - SUN | 1 - 31}] [/m {JAN - DEC[,JAN - DEC...] | *}] [/st StartTime] [/sd StartDate] [/ed EndDate] [/s computer [/u [domain\]user /p password]] [/ru {[Domain\]User | "System"} [/rp Password]]
Specific Week Syntax
schtasks /create /tn TaskName /tr TaskRun /sc monthly /mo {FIRST | SECOND | THIRD | FOURTH | LAST} /d {MON – SUN} [/m {JAN - DEC[,JAN - DEC...] | *}] [/st StartTime] [/sd StartDate] [/ed EndDate] [/s computer [/u [domain\]user /p password]] [/ru {[Domain\]User | "System"} [/rp Password]]
Lastday Syntax
schtasks /create /tn TaskName /tr TaskRun /sc monthly /mo LASTDAY /m {JAN – DEC[,JAN - DEC...] | *} [/st StartTime] [/sd StartDate] [/ed EndDate] [/s computer [/u [domain\]user /p password]] [/ru {[Domain\]User | "System"} [/rp Password]]
Specific Date Syntax
schtasks /create /tn TaskName /tr TaskRun /sc monthly /d {1 – 31} [/m {JAN - DEC[,JAN - DEC...] | *}] [/st StartTime] [/sd StartDate] [/ed EndDate] [/s computer [/u [domain\]user /p password]] [/ru {[Domain\]User | "System"} [/rp Password]]
Examples
To schedule a task for the first day of every month
The following command schedules the MyApp program to run on the first day of every month. Because the default modifier is none (no modifier), the default day is day 1, and the default month is every month, the command does not need any additional parameters.

schtasks /create /tn "My App" /tr c:\apps\myapp.exe /sc monthly

To schedule a task for the last day of every month
The following command schedules the MyApp program to run on the last day of every month. It uses the /mo parameter to specify the last day of the month and the /m parameter with the wildcard character (*) to indicate that the program runs on the last day of every month.

schtasks /create /tn "My App" /tr c:\apps\myapp.exe /sc monthly /mo lastday /m *

To schedule a task that runs every three months
The following command schedules the MyApp program to run every three months. It uses the /mo parameter to specify the interval.

schtasks /create /tn "My App" /tr c:\apps\myapp.exe /sc monthly /mo 3

To schedule a task for the second Sunday of every month
The following command schedules the MyApp program to run on the second Sunday of every month. It uses the /mo parameter to specify the second week of the month and the /d parameter to specify the day.

schtasks /create /tn "My App" /tr c:\apps\myapp.exe /sc monthly /mo SECOND /d SUN

To schedule a task for the 15th days of May and June
The following command schedules the MyApp program to run on May 15 and June 15 at 3:00 PM (15:00). It uses the /d parameter to specify the date and the /m parameter to specify the months. It also uses the /st parameter to specify the start time.

schtasks /create /tn "My App" /tr c:\apps\myapp.exe /sc monthly /d 15 /m MAY,JUN /st 15:00:00

schtasks create once

Syntax
schtasks /create /tn TaskName /tr TaskRun /sc once /st StartTime /sd StartDate [/s computer [/u [domain\]user /p password]] [/ru {[Domain\]User | "System"} [/rp Password]]

Example
To schedule a task that runs one time
The following command schedules the MyApp program to run at midnight on January 1, 2002. It uses the /ru parameter to run the task with the permissions of the user’s Administrator account and the /rp parameter to provide the password for the Administrator account.

schtasks /create /tn "My App" /tr c:\apps\myapp.exe /sc once /st 00:00:00 /sd 01/01/2002 /ru Admin23 /rp p@ssworD1

schtasks create onstart

Syntax
schtasks /create /tn TaskName /tr TaskRun /sc onstart [/sd StartDate] [/s computer [/u [domain\]user /p password]] [/ru {[Domain\]User | "System"} [/rp Password]]

Example
To schedule a task that runs every time the system starts
The following command schedules the MyApp program to run every time the system starts, beginning on March 15, 2001:

schtasks /create /tn "My App" /tr c:\apps\myapp.exe /sc onstart /sd 03/15/2001

schtasks create onlogon

Syntax
schtasks /create /tn TaskName /tr TaskRun /sc onlogon [/sd StartDate] [/s computer [/u [domain\]user /p password]] [/ru {[Domain\]User | "System"} [/rp Password]]

Example
To schedule a task that runs when a user logs on to a remote computer
The following command schedules a batch file to run every time a user (any user) logs on to the remote computer. It uses the /s parameter to specify the remote computer. Because the command is remote, all paths in the command, including the path to the batch file, refer to a path on the remote computer.

schtasks /create /tn "Start Web Site" /tr c:\myiis\webstart.bat /sc onlogon /s Server23

schtasks create onidle

Syntax
schtasks /create /tn TaskName /tr TaskRun /sc onidle /iIdleTime [/sd StartDate] [/s computer [/u [domain\]user /p password]] [/ru {[Domain\]User | "System"} [/rp Password]]

Example
To schedule a task that runs whenever the computer is idle
The following command schedules the MyApp program to run whenever the computer is idle. It uses the required /i parameter to specify that the computer must remain idle for ten minutes before the task starts.

schtasks /create /tn "My App" /tr c:\apps\myapp.exe /sc onidle /i 10

More examples
To view the example, click the example name:

To create a task that runs with System permissions

The following command schedules the MyApp program to run with permissions of the NT Authority\System account. In this example, the task is scheduled to run on the first day of every month, but you can use any schedule type for a task run with system permissions.

The command uses the /ru "System" parameter to specify the system security context. Because system tasks do not use a password, the /rp parameter is omitted.

schtasks /create /tn "My App" /tr c:\apps\myapp.exe /sc monthly /d 1 /ru "System"

In response, SchTasks.exe displays an informational message and a success message. It does not prompt for a password.


INFO: The task will be created under user name ("NT AUTHORITY\SYSTEM").
SUCCESS: The Scheduled task "My App" has successfully been created.

To create a task that runs more than one program

Each task runs only one program. However, you can create a batch file that runs multiple programs and then schedule a task to run the batch file. The following procedure demonstrates this method:

Create a batch file that starts the programs you want to run.
In this example, you create a batch file that starts Event Viewer (Eventvwr.exe) and System Monitor (Perfmon.exe).

Open a text editor, such as Notepad.
Type the name and fully qualified path to the executable file for each program. In this case, the file includes the following statements.
C:\Windows\System32\Eventvwr.exe
C:\Windows\System32\Perfmon.exe

Save the file as MyApps.bat.
Use SchTasks.exe to create a task that runs MyApps.bat.
The following command creates the Monitor task, which runs whenever anyone logs on. It uses the /tn parameter to name the task, and the /tr parameter to run MyApps.bat. It uses the /sc parameter to indicate the OnLogon schedule type and the /ru parameter to specify the Administrator account.

schtasks /create /tn Monitor /tr C:\MyApps.bat /sc onlogon /ru Reskit\Administrator

As a result of this command, whenever a user logs on to the computer, the task starts both Event Viewer and System Monitor.

schtasks change

Changes one or more of the following properties of a task.

The program that the task runs (/tr).
The user account under which the task runs (/ru).
The password for the user account (/rp).
Syntax
schtasks /change /tn TaskName [/s computer [/u [domain\]user /p password]] [/tr TaskRun] [/ru [Domain\]User | "System"] [/rp Password]

Parameters
/tn TaskName
Identifies the task to be changed. Enter the task name.
/s Computer
Specifies the name or IP address of a remote computer (with or without backslashes). The default is the local computer.
/u [domain\]user
Runs the command with the permissions of the specified user account. By default, the command runs with the permissions of the user logged on to the computer running SchTasks.
/p password
Specifies the password of the user account specified in the /u parameter. This parameter is required when the /u parameter is used.
/tr TaskRun
Changes the program that the task runs. Enter the fully qualified path and file name of an executable file, script file, or batch file. If you omit the path, SchTasks.exe assumes that the file is in the Systemroot\System32 directory. The specified program replaces the original program run by the task.
/ru [Domain\]User | "System"
Changes the user account for the task. Value Description
[Domain\]User Specifies a user account.
"System" or "" Specifies the NT Authority\System account, which is used by the operating system.

When you change the user account, you must also change the user password. If a command has an /ru parameter but not an /rp parameter, SchTasks.exe prompts for a new password and obscures the text you type.

Tasks run with with permissions of the NT Authority\System account do not require a password and SchTasks.exe does not prompt for one.

/rp Password
Changes the account password for the task. Enter the new password.
/?
Displays help at the command prompt.
Remarks
Using the /s, /u, and /p command-line options
The /u and /p command-line options are available only when you use /s. You must use /p with /u to provide the user’s password.

 
The /tn and /s parameters identify the task. The /tr, /ru, and /rp parameters specify properties of the task that you can change.
A command that uses the change operation must change at least one task property.
The NT Authority\System account does not have interactive logon rights. Users do not see and cannot interact with programs run with system permissions.
Examples
To change the program that a task runs
The following command changes the program that the Virus Check task runs from VirusCheck.exe to VirusCheck2.exe. This command uses the /tn parameter to identify the task and the /tr parameter to specify the new program for the task. (You cannot change the task name.)

schtasks /change /tn "Virus Check" /tr C:\VirusCheck2.exe

In response, SchTasks.exe displays the following success message:

SUCCESS: The parameter of the Scheduled Task "Virus Check" has been changed.
As a result of this command, the Virus Check task now runs VirusCheck2.exe.

To change the password for a remote task
The following command changes the password of the user account for the RemindMe task on the remote computer, Svr01. The command uses the /tn parameter to identify the task and the /s parameter to specify the remote computer. It uses the /rp parameter to specify the new password, p@ssWord3.

This procedure is required whenever the password for a user account expires or changes. If the password saved in a task is no longer valid, then the task does not run.

schtasks /change /tn RemindMe /s Svr01 /rp p@ssWord3

In response, SchTasks.exe displays the following success message:

SUCCESS: The parameter of the Scheduled Task "RemindMe" has been changed.
As a result of this command, the RemindMe task now runs under its original user account, but with a new password.

To change the program and user account for a task
The following command changes the program that a task runs and changes the user account under which the task runs. Essentially, it uses an old schedule for a new task. This command changes the Notepad task, which starts Notepad.exe every morning at 9:00 a.m., to start Internet Explorer instead.

The command uses the /tn parameter to identify the task. It uses the /tr parameter to change the program that the task runs and the /ru parameter to change the user account under which the task runs.

The /rp parameter, which provides the password for the user account, is omitted. You must provide a password for the account, but you can use the /rp parameter and type the password in clear text, or wait for SchTasks.exe to prompt you for a password, and then enter the password in obscured text.

schtasks /change /tn Notepad /tr "c:\program files\Internet Explorer\iexplore.exe" /ru DomainX\Admin01

In response, SchTasks.exe requests the password for the user account. It obscures the text you type, so the password is not visible.

Please enter the password for DomainX\Admin01: *********
Note that the /tn parameter identifies the task and that the /tr and /ru parameters change the properties of the task. You cannot use another parameter to identify the task and you cannot change the task name.

In response, SchTasks.exe displays the following success message:

SUCCESS: The parameter of the Scheduled Task "Notepad" has been changed.
As a result of this command, the RemindMe task now runs under its original user account, but with a new password.

To change a program to the System account
The following command changes the SecurityScript task so that it runs with permissions of the NT Authority\System account. It uses the /ru "" parameter to indicate the System account.

schtasks /change /tn SecurityScript /ru ""

In response, SchTasks.exe displays the following success message:

SUCCESS: The parameter of the Scheduled Task "SecurityScript" has been changed.
Because tasks run with System account permissions do not require a password, SchTasks.exe does not prompt for one.

schtasks run

Starts a scheduled task immediately. The run operation ignores the schedule, but uses the program file location, user account, and password saved in the task to run the task immediately.

Syntax
schtasks /run /tn TaskName [/s computer [/u [domain\]user /p password]] /?

Parameters
/tn TaskName
Identifies the task. This parameter is required.
/s Computer
Specifies the name or IP address of a remote computer (with or without backslashes). The default is the local computer.
/u [domain\]user
Runs the command with the permissions of the specified user account. By default, the command runs with the permissions of the user logged on to the computer running SchTasks.
/p password
Specifies the password of the user account specified in the /u parameter. This parameter is required when the /u parameter is used.
/?
Displays help at the command prompt.
Remarks
Using the /s, /u, and /p command-line options
The /u and /p command-line options are available only when you use /s. You must use /p with /u to provide the user’s password.

 
Use this operation to test your tasks. If a task does not run, check the Task Scheduler Service transaction log, Systemroot\SchedLgU.txt, for errors.
Running a task does not affect the task schedule and does not change the next run time scheduled for the task.
To run a task remotely, the task must be scheduled on the remote computer. When you run it, the task runs only on the remote computer. To verify that a task is running on a remote computer, use Task Manager or the Task Scheduler transaction log, Systemroot\SchedLgU.txt.
Examples
To run a task on the local computer
The following command starts the "Security Script" task.

schtasks /run /tn "Security Script"

In response, SchTasks.exe starts the script associated with the task and displays the following message:

SUCCESS: The Scheduled Task "Security Script" is running ……
To run a task on a remote computer
The following command starts the Update task on a remote computer, Svr01:

schtasks /run /tn Update /s Svr01

In this case, SchTasks.exe displays the following error message:

ERROR: Unable to run the Scheduled Task "Update".
To find the cause of the error, look in the Scheduled Tasks transaction log, C:\Windows\SchedLgU.txt on Svr01. In this case, the following entry appears in the log:


"Update.job" (update.exe) 3/26/2001 1:15:46 PM ** ERROR **
The attempt to log on to the account associated with the task failed, therefore, the task did not run.
    The specific error is:
    0×8007052e: Logon failure: unknown user name or bad password.
    Verify that the task’s Run-as name and password are valid and try again.

Apparently, the user name or password in the task is not valid on the system. The following schtasks /change command updates the user name and password for the Update task on Svr01:

schtasks /change /tn Update /s Svr01 /ru Administrator /rp PassW@rd3

After the change command completes, the run command is repeated. This time, the Update.exe program starts and SchTasks.exe displays the following message:

SUCCESS: The Scheduled Task "Update" is running……
schtasks end

Stops a program started by a task.

Syntax
schtasks /end /tn TaskName [/s computer [/u [domain\]user /p password]] /?

Parameters
/tn TaskName
Identifies the task that started the program. This parameter is required.
/s Computer
Specifies the name or IP address of a remote computer (with or without backslashes). The default is the local computer.
/u [domain\]user
Runs the command with the permissions of the specified user account. By default, the command runs with the permissions of the user logged on to the computer running SchTasks.
/p password
Specifies the password of the user account specified in the /u parameter. This parameter is required when the /u parameter is used.
/?
Displays help.
Remarks
Using the /s, /u, and /p command-line options
The /u and /p command-line options are available only when you use /s. You must use /p with /u to provide the user’s password.

 
SchTasks.exe ends only the instances of a program started by a scheduled task. To stop other processes, use TaskKill, a tool included in Windows XP Professional. For more information about TaskKill, see Taskkill.
Examples
To end a task on a local computer
The following command stops the instance of Notepad.exe that was started by the My Notepad task:

schtasks /end /tn "My Notepad"

In response, SchTasks.exe stops the instance of Notepad.exe that the task started, and it displays the following success message:

SUCCESS: The Scheduled Task "My Notepad" has been terminated successfully.
To end a task on a remote computer
The following command stops the instance of Internet Explorer that was started by the InternetOn task on the remote computer, Svr01:

schtasks /end /tn InternetOn /s Svr01

In response, SchTasks.exe stops the instance of Internet Explorer that the task started, and it displays the following success message:

SUCCESS: The Scheduled Task "InternetOn" has been terminated successfully.
schtasks delete

Deletes a scheduled task.

Syntax
schtasks /delete /tn {TaskName | *} [/f] [/s computer [/u [domain\]user /p password]] [/?]

Parameters
/tn {TaskName | *}
Identifies the task being deleted. This parameter is required. Value Description
TaskName Deletes the named task.
* Deletes all scheduled tasks on the computer.

/f
Suppresses the confirmation message. The task is deleted without warning.
/s Computer
Specifies the name or IP address of a remote computer (with or without backslashes). The default is the local computer.
/u [domain\]user
Runs the command with the permissions of the specified user account. By default, the command runs with the permissions of the user logged on to the computer running SchTasks.
/p password
Specifies the password of the user account specified in the /u parameter. This parameter is required when the /u parameter is used.
/?
Displays help at the command prompt.
Remarks
Using the /s, /u, and /p command-line options
The /u and /p command-line options are available only when you use /s. You must use /p with /u to provide the user’s password.

 
The delete operation deletes the task from the schedule. It does not delete the program that the task runs or interrupt a running program.
The delete * command deletes all tasks scheduled for the computer, not just the tasks scheduled by the current user.
Examples
To delete a task from the schedule of a remote computer
The following command deletes the "Start Mail" task from the schedule of a remote computer. It uses the /s parameter to identify the remote computer.

schtasks /delete /tn "Start Mail" /s Svr16

In response, SchTasks.exe displays the following confirmation message. To delete the task, type y. To cancel the command, type n:

WARNING: Are you sure you want to remove the task "Start Mail" (Y/N )? y
SUCCESS: The Scheduled Task "Start Mail" was successfully deleted.
To delete all tasks scheduled for the local computer
The following command deletes all tasks from the schedule of the local computer, including tasks scheduled by other users. It uses the /tn * parameter to represent all tasks on the computer and the /f parameter to suppress the confirmation message.

schtasks /delete /tn * /f

In response, SchTasks.exe displays the following success messages indicating that the only task scheduled, SecureScript, is deleted.

SUCCESS: The Scheduled Task "SecureScript" was successfully deleted.
schtasks query

Displays all tasks scheduled to run on the computer, including those scheduled by other users.

Syntax
schtasks [/query] [/fo {TABLE | LIST | CSV}] [/nh] [/v] [/s computer [/u [domain\]user /p password]]

Parameters
[/query]
The operation name is optional. Typing schtasks without any parameters performs a query.
/fo {TABLE | LIST | CSV}
Specifies the output format. TABLE is the default.
/nh
Omits column headings from the table display. This parameter is valid with the TABLE and CSV output formats.
/v
Adds advanced properties of the tasks to the display.
Queries using /v should be formatted as LIST or CSV.

/s Computer
Specifies the name or IP address of a remote computer (with or without backslashes). The default is the local computer.
/u [domain\]user
Runs the command with the permissions of the specified user account. By default, the command runs with the permissions of the user logged on to the computer running SchTasks.
/p password
Specifies the password of the user account specified in the /u parameter. This parameter is required when the /u parameter is used.
/?
Displays help at the command prompt.
Remarks
Using the /s, /u, and /p command-line options
The /u and /p command-line options are available only when you use /s. You must use /p with /u to provide the user’s password.

 
The query operation lists all tasks scheduled for the computer, not just the tasks scheduled by the current user.
Examples
To display the scheduled tasks on the local computer
The following commands display all tasks scheduled for the local computer. These commands produce the same result and can be used interchangeably.

schtasks

schtasks /query

In response, SchTasks.exe displays the tasks in the default, simple table format, as shown in the following table:


TaskName                  Next Run Time            Status
========================= ======================== ==============
Microsoft Outlook         At logon time            
SecureScript              14:42:00 PM , 2/4/2001   

To display advanced properties scheduled tasks
The following command requests a detailed display of the tasks on the local computer. It uses the /v parameter to request a detailed (verbose) display and the /fo LIST parameter to format the display as a list for easy reading. You can use this command to verify that a task you created has the intended recurrence pattern.

schtasks /query /fo LIST /v

In response, SchTasks.exe displays a detailed property list for all tasks. The following display shows the task list for a task scheduled to run at 4:00 A.M. on the last Friday of every month:


HostName:                                  RESKIT01
TaskName:                                  SecureScript
Next Run Time:                             4:00:00 AM , 3/30/2001
Status:                                    Not yet run
Last Run Time:                             Never
Last Result:                               0
Creator:                                   user01
Schedule:                                  At 4:00 AM on the last Fri of every month, starting 3/24/2001
Task To Run:                               C:\WINDOWS\system32\notepad.exe
Start In:                                  notepad.exe
Comment:                                   N/A
Scheduled Task State:                      Enabled
Scheduled Type:                            Monthly
Modifier:                                  Last FRIDAY
Start Time:                                4:00:00 AM
Start Date:                                3/24/2001
End Date:                                  N/A
Days:                                      FRIDAY
Months:                                    JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC
Run As User:                               RESKIT\user01
Delete Task If Not Rescheduled:            Enabled
Stop Task If Runs X Hours and X Mins:      72:0
Repeat: Until Time:                        Disabled
Repeat: Duration:                          Disabled
Repeat: Stop If Still Running:             Disabled
Idle: Start Time(For IDLE Scheduled Type): Disabled
Idle: Only Start If Idle for X Minutes:    Disabled
Idle: If Not Idle Retry For X Minutes:     Disabled
Idle: Stop Task If Idle State End:         Disabled
Power Mgmt: No Start On Batteries:         Disabled
Power Mgmt: Stop On Battery Mode:          Disabled

To log tasks scheduled for a remote computer
The following command requests a list of tasks scheduled for a remote computer, and adds the tasks to a comma-separated log file on the local computer. You can use this command format to collect and track tasks that are scheduled for multiple computers.

The command uses the /s parameter to identify the remote computer, Reskit16, the /fo parameter to specify the format and the /nh parameter to suppress the column headings. The >> append symbol redirects the output to the task log, p0102.csv, on the local computer, Svr01. Because the command runs on the remote computer, the local computer path must be fully qualified.

schtasks /query /s Reskit16 /fo csv /nh >> \\svr01\data\tasklogs\p0102.csv

In response, SchTasks.exe adds the tasks scheduled for the Reskit16 computer to the p0102.csv file on the local computer, Svr01.

Remarks
SchTasks.exe performs operations similar to those in Scheduled Tasks in Control Panel. You can use either tool to create, delete, configure, or display scheduled tasks.
Typing schtasks without any parameters performs a query.
The user must be a member of the Administrators group on the computer that the command affects.
To verify that a scheduled task ran or to find out why a scheduled task did not run, see the Task Scheduler service transaction log, Systemroot\SchedLgU.txt. This log records attempted runs initiated by all tools that use the service, including Scheduled Tasks and SchTasks.exe.
On rare occasions, task files become corrupted. Corrupted tasks do not run. When you try to perform an operation on corrupted tasks, SchTasks.exe displays the following error message:
ERROR: The data is invalid.
You cannot recover corrupted tasks. To restore the task scheduling features of the system, use SchTasks.exe or Scheduled Tasks to delete the tasks from the system and reschedule them.

SchTasks.exe replaces At.exe, a tool included in previous versions of Windows.

2006年06月10日

preg match

by SnowStorm on April 23 2004, 18:02


How could i write a preg match to return this stats.php?id=1643937 in code like <p>Click on the number shown in the image to proceed to <a href="stats.php?id=1643937">Snow-Storm</a>’s …

i was trying
[php]
preg_match("/stats.php?id=([0-9]+)/", $ktmp, $report);
[/php]

But thats not working, any ideas?




RE: preg match

by honcho on April 23 2004, 23:23


Your problem is probably that . and ? are control characters and not literals. Try this:
[php]
preg_match("/stats\.php\?id=([0-9]+)/", $ktmp, $report);
[/php]




RE: preg match

by SnowStorm on April 24 2004, 01:03


:) thank you.. now could you tell me why
[php]
preg_match_all("/<td>([0-9.]+)<\/td>/", $ktmp, $matches);

//also tried
preg_match_all("/([0-9,.]+)<\/td>/", $ktmp, $matches);
[/php]

Wont return instances like:
[php]
<td>16,264</td>
<td>1,378</td>
[/php]




RE: preg match

by honcho on April 24 2004, 10:15


The character class in the first one should include a comma too, but other than that, it looks fine.




RE: preg match

by SnowStorm on April 24 2004, 10:47


hmm well there are these instances that it should find:
[php]
<tr>
<td><b>Rank:</b></td>
<td>16,181</td>
</tr>
<tr>
<td><b>Army Size:</b></td>
<td>1,386</td>
</tr>
<tr>
<td><b>Treasury:</b></td>
<td>45,053</td>
</tr>
[/php]

And then using print_r($matches); it returns:
[php]
Array
(
[0] => Array
(
)
[1] => Array
(
)
)
[/php]




RE: preg match

by honcho on April 24 2004, 13:35


I just tested it and it seems fine. Make sure $ktmp actually contains what you think it does right before the call to preg_match_all().




RE: preg match

by SnowStorm on April 24 2004, 15:29


had to change it to a case-insensitive search, and now it works :) thanks.
http://codewalkers.com

引言

    正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来:(1)检查一个串中是否含有符合某个规则的子串,并且可以得到这个子串;(2)根据匹配规则对字符串进行灵活的替换操作。

    正则表达式学习起来其实是很简单的,不多的几个较为抽象的概念也很容易理解。之所以很多人感觉正则表达式比较复杂,一方面是因为大多数的文档没有做到由浅入深地讲解,概念上没有注意先后顺序,给读者的理解带来困难;另一方面,各种引擎自带的文档一般都要介绍它特有的功能,然而这部分特有的功能并不是我们首先要理解的。

    文章中的每一个举例,都可以点击进入到测试页面进行测试。闲话少说,开始。


1. 正则表达式规则

1.1 普通字符

    字母、数字、汉字、下划线、以及后边章节中没有特殊定义的标点符号,都是"普通字符"。表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符。

    举例1:表达式 "c",在匹配字符串 "abcde" 时,匹配结果是:成功;匹配到的内容是:"c";匹配到的位置是:开始于2,结束于3。(注:下标从0开始还是从1开始,因当前编程语言的不同而可能不同)

    举例2:表达式 "bcd",在匹配字符串 "abcde" 时,匹配结果是:成功;匹配到的内容是:"bcd";匹配到的位置是:开始于1,结束于4。


1.2 简单的转义字符

    一些不便书写的字符,采用在前面加 "\" 的方法。这些字符其实我们都已经熟知了。

表达式

可匹配

\r, \n

代表回车和换行符

\t

制表符

\\

代表 "\" 本身

    还有其他一些在后边章节中有特殊用处的标点符号,在前面加 "\" 后,就代表该符号本身。比如:^, $ 都有特殊意义,如果要想匹配字符串中 "^" 和 "$" 字符,则表达式就需要写成 "\^" 和 "\$"。

表达式

可匹配

\^

匹配 ^ 符号本身

\$

匹配 $ 符号本身

\.

匹配小数点(.)本身

    这些转义字符的匹配方法与 "普通字符" 是类似的。也是匹配与之相同的一个字符。

    举例1:表达式 "\$d",在匹配字符串 "abc$de" 时,匹配结果是:成功;匹配到的内容是:"$d";匹配到的位置是:开始于3,结束于5。


1.3 能够与 ‘多种字符’ 匹配的表达式

    正则表达式中的一些表示方法,可以匹配 ‘多种字符’ 其中的任意一个字符。比如,表达式 "\d" 可以匹配任意一个数字。虽然可以匹配其中任意字符,但是只能是一个,不是多个。这就好比玩扑克牌时候,大小王可以代替任意一张牌,但是只能代替一张牌。

表达式

可匹配

\d

任意一个数字,0~9 中的任意一个

\w

任意一个字母或数字或下划线,也就是 A~Z,a~z,0~9,_ 中任意一个

\s

包括空格、制表符、换页符等空白字符的其中任意一个

.

小数点可以匹配除了换行符(\n)以外的任意一个字符

    举例1:表达式 "\d\d",在匹配 "abc123" 时,匹配的结果是:成功;匹配到的内容是:"12";匹配到的位置是:开始于3,结束于5。

    举例2:表达式 "a.\d",在匹配 "aaa100" 时,匹配的结果是:成功;匹配到的内容是:"aa1";匹配到的位置是:开始于1,结束于4。


1.4 自定义能够匹配 ‘多种字符’ 的表达式

    使用方括号 [ ] 包含一系列字符,能够匹配其中任意一个字符。用 [^ ] 包含一系列字符,则能够匹配其中字符之外的任意一个字符。同样的道理,虽然可以匹配其中任意一个,但是只能是一个,不是多个。

表达式

可匹配

[ab5@]

匹配 "a" 或 "b" 或 "5" 或 "@"

[^abc]

匹配 "a","b","c" 之外的任意一个字符

[f-k]

匹配 "f"~"k" 之间的任意一个字母

[^A-F0-3]

匹配 "A"~"F","0"~"3" 之外的任意一个字符

    举例1:表达式 "[bcd][bcd]" 匹配 "abc123" 时,匹配的结果是:成功;匹配到的内容是:"bc";匹配到的位置是:开始于1,结束于3。

    举例2:表达式 "[^abc]" 匹配 "abc123" 时,匹配的结果是:成功;匹配到的内容是:"1";匹配到的位置是:开始于3,结束于4。


1.5 修饰匹配次数的特殊符号

    前面章节中讲到的表达式,无论是只能匹配一种字符的表达式,还是可以匹配多种字符其中任意一个的表达式,都只能匹配一次。如果使用表达式再加上修饰匹配次数的特殊符号,那么不用重复书写表达式就可以重复匹配。

    使用方法是:"次数修饰"放在"被修饰的表达式"后边。比如:"[bcd][bcd]" 可以写成 "[bcd]{2}"。

表达式

作用

{n}

表达式重复n次,比如:"\w{2}" 相当于 "\w\w""a{5}" 相当于 "aaaaa"

{m,n}

表达式至少重复m次,最多重复n次,比如:"ba{1,3}"可以匹配 "ba"或"baa"或"baaa"

{m,}

表达式至少重复m次,比如:"\w\d{2,}"可以匹配 "a12","_456","M12344"…

?

匹配表达式0次或者1次,相当于 {0,1},比如:"a[cd]?"可以匹配 "a","ac","ad"

+

表达式至少出现1次,相当于 {1,},比如:"a+b"可以匹配 "ab","aab","aaab"…

*

表达式不出现或出现任意次,相当于 {0,},比如:"\^*b"可以匹配 "b","^^^b"…

    举例1:表达式 "\d+\.?\d*" 在匹配 "It costs $12.5" 时,匹配的结果是:成功;匹配到的内容是:"12.5";匹配到的位置是:开始于10,结束于14。

    举例2:表达式 "go{2,8}gle" 在匹配 "Ads by goooooogle" 时,匹配的结果是:成功;匹配到的内容是:"goooooogle";匹配到的位置是:开始于7,结束于17。


1.6 其他一些代表抽象意义的特殊符号

    一些符号在表达式中代表抽象的特殊意义:

表达式

作用

^

与字符串开始的地方匹配,不匹配任何字符

$

与字符串结束的地方匹配,不匹配任何字符

\b

匹配一个单词边界,也就是单词和空格之间的位置,不匹配任何字符

    进一步的文字说明仍然比较抽象,因此,举例帮助大家理解。

    举例1:表达式 "^aaa" 在匹配 "xxx aaa xxx" 时,匹配结果是:失败。因为 "^" 要求与字符串开始的地方匹配,因此,只有当 "aaa" 位于字符串的开头的时候,"^aaa" 才能匹配,比如:"aaa xxx xxx"

    举例2:表达式 "aaa$" 在匹配 "xxx aaa xxx" 时,匹配结果是:失败。因为 "$" 要求与字符串结束的地方匹配,因此,只有当 "aaa" 位于字符串的结尾的时候,"aaa$" 才能匹配,比如:"xxx xxx aaa"

    举例3:表达式 ".\b." 在匹配 "@@@abc" 时,匹配结果是:成功;匹配到的内容是:"@a";匹配到的位置是:开始于2,结束于4。
    进一步说明:"\b" 与 "^" 和 "$" 类似,本身不匹配任何字符,但是它要求它在匹配结果中所处位置的左右两边,其中一边是 "\w" 范围,另一边是 非"\w" 的范围。

    举例4:表达式 "\bend\b" 在匹配 "weekend,endfor,end" 时,匹配结果是:成功;匹配到的内容是:"end";匹配到的位置是:开始于15,结束于18。

    一些符号可以影响表达式内部的子表达式之间的关系:

表达式

作用

|

左右两边表达式之间 "或" 关系,匹配左边或者右边

( )

(1). 在被修饰匹配次数的时候,括号中的表达式可以作为整体被修饰
(2). 取匹配结果的时候,括号中的表达式匹配到的内容可以被单独得到

    举例5:表达式 "Tom|Jack" 在匹配字符串 "I’m Tom, he is Jack" 时,匹配结果是:成功;匹配到的内容是:"Tom";匹配到的位置是:开始于4,结束于7。匹配下一个时,匹配结果是:成功;匹配到的内容是:"Jack";匹配到的位置时:开始于15,结束于19。

    举例6:表达式 "(go\s*)+" 在匹配 "Let’s go go go!" 时,匹配结果是:成功;匹配到内容是:"go go go";匹配到的位置是:开始于6,结束于14。

    举例7:表达式 "¥(\d+\.?\d*)" 在匹配 "$10.9,¥20.5" 时,匹配的结果是:成功;匹配到的内容是:"¥20.5";匹配到的位置是:开始于6,结束于10。单独获取括号范围匹配到的内容是:"20.5"。


2. 正则表达式中的一些高级规则

2.1 匹配次数中的贪婪与非贪婪

    在使用修饰匹配次数的特殊符号时,有几种表示方法可以使同一个表达式能够匹配不同的次数,比如:"{m,n}", "{m,}", "?", "*", "+",具体匹配的次数随被匹配的字符串而定。这种重复匹配不定次数的表达式在匹配过程中,总是尽可能多的匹配。比如,针对文本 "dxxxdxxxd",举例如下:

表达式

匹配结果

(d)(\w+)

"\w+" 将匹配第一个 "d" 之后的所有字符 "xxxdxxxd"

(d)(\w+)(d)

"\w+" 将匹配第一个 "d" 和最后一个 "d" 之间的所有字符 "xxxdxxx"。虽然 "\w+" 也能够匹配上最后一个 "d",但是为了使整个表达式匹配成功,"\w+" 可以 "让出" 它本来能够匹配的最后一个 "d"

    由此可见,"\w+" 在匹配的时候,总是尽可能多的匹配符合它规则的字符。虽然第二个举例中,它没有匹配最后一个 "d",但那也是为了让整个表达式能够匹配成功。同理,带 "*" 和 "{m,n}" 的表达式都是尽可能地多匹配,带 "?" 的表达式在可匹配可不匹配的时候,也是尽可能的 "要匹配"。这 种匹配原则就叫作 "贪婪" 模式 。

    非贪婪模式:

    在修饰匹配次数的特殊符号后再加上一个 "?" 号,则可以使匹配次数不定的表达式尽可能少的匹配,使可匹配可不匹配的表达式,尽可能的 "不匹配"。这种匹配原则叫作 "非贪婪" 模式,也叫作 "勉强" 模式。如果少匹配就会导致整个表达式匹配失败的时候,与贪婪模式类似,非贪婪模式会最小限度的再匹配一些,以使整个表达式匹配成功。举例如下,针对文本 "dxxxdxxxd" 举例:

表达式

匹配结果

(d)(\w+?)

"\w+?" 将尽可能少的匹配第一个 "d" 之后的字符,结果是:"\w+?" 只匹配了一个 "x"

(d)(\w+?)(d)

为了让整个表达式匹配成功,"\w+?" 不得不匹配 "xxx" 才可以让后边的 "d" 匹配,从而使整个表达式匹配成功。因此,结果是:"\w+?" 匹配 "xxx"

    更多的情况,举例如下:

    举例1:表达式 "<td>(.*)</td>" 与字符串 "<td><p>aa</p></td> <td><p>bb</p></td>" 匹配时,匹配的结果是:成功;匹配到的内容是 "<td><p>aa</p></td> <td><p>bb</p></td>" 整个字符串, 表达式中的 "</td>" 将与字符串中最后一个 "</td>" 匹配。

    举例2:相比之下,表达式 "<td>(.*?)</td>" 匹配举例1中同样的字符串时,将只得到 "<td><p>aa</p></td>", 再次匹配下一个时,可以得到第二个 "<td><p>bb</p></td>"。


2.2 反向引用 \1, \2…

    表达式在匹配时,表达式引擎会将小括号 "( )" 包含的表达式所匹配到的字符串记录下来。在获取匹配结果的时候,小括号包含的表达式所匹配到的字符串可以单独获取。这一点,在前面的举例中,已经多次展示了。在实际应用场合中,当用某种边界来查找,而所要获取的内容又不包含边界时,必须使用小括号来指定所要的范围。比如前面的 "<td>(.*?)</td>"。

    其实,"小括号包含的表达式所匹配到的字符串" 不仅是在匹配结束后才可以使用,在匹配过程中也可以使用。表达式后边的部分,可以引用前面 "括号内的子匹配已经匹配到的字符串"。引用方法是 "\" 加上一个数字。"\1" 引用第1对括号内匹配到的字符串,"\2" 引用第2对括号内匹配到的字符串……以此类推,如果一对括号内包含另一对括号,则外层的括号先排序号。换句话说,哪一对的左括号 "(" 在前,那这一对就先排序号。

    举例如下:

    举例1:表达式 "(‘|")(.*?)(\1)" 在匹配 " ‘Hello’, "World" " 时,匹配结果是:成功;匹配到的内容是:" ‘Hello’ "。再次匹配下一个时,可以匹配到 " "World" "。

    举例2:表达式 "(\w)\1{4,}" 在匹配 "aa bbbb abcdefg ccccc 111121111 999999999" 时,匹配结果是:成功;匹配到的内容是 "ccccc"。再次匹配下一个时,将得到 999999999。这个表达式要求 "\w" 范围的字符至少重复5次,注意与 "\w{5,}" 之间的区别

    举例3:表达式 "<(\w+)\s*(\w+(=(‘|").*?\4)?\s*)*>.*?</\1>" 在匹配 "<td id=’td1′ style="bgcolor:white"></td>" 时,匹配结果是成功。如果 "<td>" 与 "</td>" 不配对,则会匹配失败;如果改成其他配对,也可以匹配成功。


2.3 预搜索,不匹配;反向预搜索,不匹配

    前面的章节中,我讲到了几个代表抽象意义的特殊符号:"^","$","\b"。它们都有一个共同点,那就是:它们本身不匹配任何字符,只是对 "字符串的两头" 或者 "字符之间的缝隙" 附加了一个条件。理解到这个概念以后,本节将继续介绍另外一种对 "两头" 或者 "缝隙" 附加条件的,更加灵活的表示方法。

    正向预搜索:"(?=xxxxx)","(?!xxxxx)"

    格式:"(?=xxxxx)",在被匹配的字符串中,它对所处的 "缝隙" 或者 "两头" 附加的条件是:所在缝隙的右侧,必须能够匹配上 xxxxx 这部分的表达式。因为它只是在此作为这个缝隙上附加的条件,所以它并不影响后边的表达式去真正匹配这个缝隙之后的字符。这就类似 "\b",本身不匹配任何字符。"\b" 只是将所在缝隙之前、之后的字符取来进行了一下判断,不会影响后边的表达式来真正的匹配。

    举例1:表达式 "Windows (?=NT|XP)" 在匹配 "Windows 98, Windows NT, Windows 2000" 时,将只匹配 "Windows NT" 中的 "Windows ",其他的 "Windows " 字样则不被匹配。

    举例2:表达式 "(\w)((?=\1\1\1)(\1))+" 在匹配字符串 "aaa ffffff 999999999" 时,将可以匹配6个"f"的前4个,可以匹配9个"9"的前7个。这个表达式可以读解成:重复4次以上的字母数字,则匹配其剩下最后2位之前的部分。当然,这个表达式可以不这样写,在此的目的是作为演示之用。

    格式:"(?!xxxxx)",所在缝隙的右侧,必须不能匹配 xxxxx 这部分表达式。

    举例3:表达式 "((?!\bstop\b).)+" 在匹配 "fdjka ljfdl stop fjdsla fdj" 时,将从头一直匹配到 "stop" 之前的位置,如果字符串中没有 "stop",则匹配整个字符串。

    举例4:表达式 "do(?!\w)" 在匹配字符串 "done, do, dog" 时,只能匹配 "do"。在本条举例中,"do" 后边使用 "(?!\w)" 和使用 "\b" 效果是一样的。

    反向预搜索:"(?<=xxxxx)","(?<!xxxxx)"

    这两种格式的概念和正向预搜索是类似的,反向预搜索要求的条件是:所在缝隙的 "左侧",两种格式分别要求必须能够匹配和必须不能够匹配指定表达式,而不是去判断右侧。与 "正向预搜索" 一样的是:它们都是对所在缝隙的一种附加条件,本身都不匹配任何字符。

    举例5:表达式 "(?<=\d{4})\d+(?=\d{4})" 在匹配 "1234567890123456" 时,将匹配除了前4个数字和后4个数字之外的中间8个数字。由于 JScript.RegExp 不支持反向预搜索,因此,本条举例不能够进行演示。很多其他的引擎可以支持反向预搜索,比如:Java 1.4 以上的 java.util.regex 包,.NET 中System.Text.RegularExpressions 命名空间,boost::regex 以及 GRETA 正则表达式库等。


3. 其他通用规则

    还有一些在各个正则表达式引擎之间比较通用的规则,在前面的讲解过程中没有提到。

3.1 表达式中,可以使用 "\xXX" 和 "\uXXXX" 表示一个字符("X" 表示一个十六进制数)

形式

字符范围

\xXX

编号在 0 ~ 255 范围的字符,比如:空格可以使用 "\x20" 表示

\uXXXX

任何字符可以使用 "\u" 再加上其编号的4位十六进制数表示,比如:"\u4E2D"

3.2 在表达式 "\s","\d","\w","\b" 表示特殊意义的同时,对应的大写字母表示相反的意义

表达式

可匹配

\S

匹配所有非空白字符("\s" 可匹配各个空白字符)

\D

匹配所有的非数字字符

\W

匹配所有的字母、数字、下划线以外的字符

\B

匹配非单词边界,即左右两边都是 "\w" 范围或者左右两边都不是 "\w" 范围时的字符缝隙

3.3 在表达式中有特殊意义,需要添加 "\" 才能匹配该字符本身的字符汇总

字符

说明

^

匹配输入字符串的开始位置。要匹配 "^" 字符本身,请使用 "\^"

$

匹配输入字符串的结尾位置。要匹配 "$" 字符本身,请使用 "\$"

( )

标记一个子表达式的开始和结束位置。要匹配小括号,请使用 "\(" 和 "\)"

[ ]

用来自定义能够匹配 ‘多种字符’ 的表达式。要匹配中括号,请使用 "\[" 和 "\]"

{ }

修饰匹配次数的符号。要匹配大括号,请使用 "\{" 和 "\}"

.

匹配除了换行符(\n)以外的任意一个字符。要匹配小数点本身,请使用 "\."

?

修饰匹配次数为 0 次或 1 次。要匹配 "?" 字符本身,请使用 "\?"

+

修饰匹配次数为至少 1 次。要匹配 "+" 字符本身,请使用 "\+"

*

修饰匹配次数为 0 次或任意次。要匹配 "*" 字符本身,请使用 "\*"

|

左右两边表达式之间 "或" 关系。匹配 "|" 本身,请使用 "\|"

3.4 括号 "( )" 内的子表达式,如果希望匹配结果不进行记录供以后使用,可以使用 "(?:xxxxx)" 格式

    举例1:表达式 "(?:(\w)\1)+" 匹配 "a bbccdd efg" 时,结果是 "bbccdd"。括号 "(?:)" 范围的匹配结果不进行记录,因此 "(\w)" 使用 "\1" 来引用。

3.5 常用的表达式属性设置简介:Ignorecase,Singleline,Multiline,Global

表达式属性

说明

Ignorecase

默认情况下,表达式中的字母是要区分大小写的。配置为 Ignorecase 可使匹配时不区分大小写。有的表达式引擎,把 "大小写" 概念延伸至 UNICODE 范围的大小写。

Singleline

默认情况下,小数点 "." 匹配除了换行符(\n)以外的字符。配置为 Singleline 可使小数点可匹配包括换行符在内的所有字符。

Multiline

默认情况下,表达式 "^" 和 "$" 只匹配字符串的开始 ① 和结尾 ④ 位置。如:

①xxxxxxxxx②\n
③xxxxxxxxx④

配置为 Multiline 可以使 "^" 匹配 ① 外,还可以匹配换行符之后,下一行开始前 ③ 的位置,使 "$" 匹配 ④ 外,还可以匹配换行符之前,一行结束 ② 的位置。

Global

主要在将表达式用来替换时起作用,配置为 Global 表示替换所有的匹配。


4. 综合提示

4.1 如果要要求表达式所匹配的内容是整个字符串,而不是从字符串中找一部分,那么可以在表达式的首尾使用 "^" 和 "$",比如:"^\d+$" 要求整个字符串只有数字。

4.2 如果要求匹配的内容是一个完整的单词,而不会是单词的一部分,那么在表达式首尾使用 "\b",比如:使用 "\b(if|while|else|void|int……)\b" 来匹配程序中的关键字

4.3 表达式不要匹配空字符串。否则会一直得到匹配成功,而结果什么都没有匹配到。比如:准备写一个匹配 "123"、"123."、"123.5"、".5" 这几种形式的表达式时,整数、小数点、小数数字都可以省略,但是不要将表达式写成:"\d*\.?\d*",因为如果什么都没有,这个表达式也可以匹配成功。更好的写法是:"\d+\.?\d*|\.\d+"

4.4 能匹配空字符串的子匹配不要循环无限次。如果括号内的子表达式中的每一部分都可以匹配 0 次,而这个括号整体又可以匹配无限次,那么情况可能比上一条所说的更严重,匹配过程中可能死循环。虽然现在有些正则表达式引擎已经通过办法避免了这种情况出现死循环了,比如 .NET 的正则表达式,但是我们仍然应该尽量避免出现这种情况。如果我们在写表达式时遇到了死循环,也可以从这一点入手,查找一下是否是本条所说的原因。

4.5 合理选择贪婪模式与非贪婪模式,参见话题讨论

4.6 或 "|" 的左右两边,对某个字符最好只有一边可以匹配,这样,不会因为 "|" 两边的表达式因为交换位置而有所不同。

2006年06月08日
I've just performed a similar function using
cURL - after reading August's PHP Architect.
Here's my solution.

//Look for all URLs inside href='' and src=''
attributes.
$badlink = false;
$href = '!(src|href)=\s?\'?"?([^\' "]*)\'?"?!i';
if (preg_match_all($href,
$string,$html_href_urls) > 0){
   foreach ($html_href_urls[2] as $url){
      if (substr($url, 0, strlen($fqdn)) != $fqdn){
         //URL doesn't have valid or complete http
path.
        $invalid_urls[] = $url;
        $badlink = true;
      } else {
         //Check for existence of $url
        $ch = curl_init("{$url}");
        curl_setopt($ch,
CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch,
CURLOPT_FOLLOWLOCATION, 1);
        $output = curl_exec($ch);
        if ($output === false || strstr
($output, "HTTP/1.1 404")){//Since server
supplies a valid HTML file for missing URLS,
also need to look for 404 error in output.
           $out['content'] .= "<p>URL $url in the
html mail doesn't appear to exist.</p>";
           $badlink = true;
         } else {
            $out['content'] .= "<p>URL <a
href='$url' target='_new'>$url</a> found</p>";
         }
      }
   }
} else {
   $out['content'] .= "<p>No matches of $href or
pattern not found.</p>";
   $badlink = true;
}

Tim was looking to try something new, so I decided to introduce him to Client URL (CURL) functions. As the example at hand, we looked at hitting the USPS site to lookup city and states based on ZIP code.

For the uninitiated, CURL basically lets you programmatically simulate a user browsing a web site. You can POST, GET, PUT, maintain cookies and session information. In the following example we are using a technique called "screen scraping" which is rarely recommended, but a good skill to have because sometimes its the only solution.

The reason its bad is because it is extremely fragile. If a webmaster of the site you are accessing makes even a slight change, it could break your page parsing. The other reason to shy away from this is some web sites really don’t like when you do this. As a rule, if the webmaster of the site you are scraping contacts you and wants you to stop, you should, immediately. Though you should also recommend they provide the info you are scraping as a service through something like REST or SOAP. It would be very Web 2.0 of them to comply, it’s worth a shot.

Anyway, check out this example code, it’s kinda fun.

<?php
ob_start();
 
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://zip4.usps.com/zip4/zcl_3_results.jsp");
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_POSTFIELDS, "zip5=".$_GET['zip']);
 
$data = curl_exec($ch);
$string = ob_get_contents();
 
ob_end_clean();
 
list(,$second) = explode(‘Actual City name’, $string);
list($first) = explode(‘images/spacer.gif’, $second);
$junk = explode(?\n?,$first);
 
list($city,$state) = explode(‘, ‘,trim(strip_tags($junk[6])));
 
$city = ucwords(strtolower($city));
 
print $city.’,’.$state;
?>