篱笆外小雨


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

.md 文档语法规则

发表于 2017-05-12 | 分类于 博客相关 | 阅读次数

在md文档中添加图片

方法一:
叹号! + 方括号[图片描述 ] + 括号(图片URL )

1
![img](url)

方法二:
使用HTML语法规则

1
img src="url"

基于Lucene的Java Web 搜索引擎设计

发表于 2017-05-12 | 分类于 Java | 阅读次数

这是一个简易的搜索引擎。该设计是针对PDF文档的搜索。用户提供关键词,搜索引擎返回搜索结果到用户界面,用户通过返回的超链接可查看文档的详细内容。

设计概述

首先,通过BuildIndex创建文档的索引。然后,将关键词作为Search的参数,返回查询结构,文档内容高亮显示。

jar包

img

创建索引(BuildIndex.java)

创建索引的过程就是将每个文档转化成Document对象,然后调用IndexWriter的addDocument方法将Document对象添加到索引中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public static void run(String sdir, String indexPath) throws Exception{
File fdir=new File(sdir);
File[] flist=fdir.listFiles();
Document doc;
Analyzer analyzer=new IKAnalyzer();
IndexWriterConfig conf = new IndexWriterConfig(analyzer);
conf.setOpenMode(IndexWriterConfig.OpenMode.CREATE);
Directory dir = FSDirectory.open(Paths.get(indexPath));
IndexWriter idxWriter=new IndexWriter(dir,conf);
for(File f : flist){
doc=buildDoc(f);
idxWriter.addDocument(doc);
}
idxWriter.close();
}
/**
* 为一篇文档建立document对象
* @throws FileNotFoundException
* */
private static Document buildDoc(File f) throws Exception{
String fname=f.getPath();
Document doc=new Document();
FieldType offsetsType = new FieldType(TextField.TYPE_STORED);
offsetsType.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);
Field body = new Field("contents", getContent(f), offsetsType);
doc.add(body);
doc.add(new StringField("path",fname,Field.Store.YES));
return doc;
}

提取PDF文档内容(ReadPDF.java)

使用PDF-Box所提供的库从PDF文档中提取内容。
PDFbox是一个开源的、基于Java的、支持PDF文档生成的工具库,它可以用于创建新的PDF文档,修改现有的PDF文档,还可以从PDF文档中提取所需的内容。

1
2
3
4
5
6
7
8
9
10
11
12
public static String readPdf(String path) throws Exception { 
StringBuffer content = new StringBuffer("");// 文档内容
FileInputStream fis = new FileInputStream(path);
PDFParser p = new PDFParser(new RandomAccessBuffer(fis));
p.parse();
PDDocument document= p.getPDDocument();
PDFTextStripper ts = new PDFTextStripper();
content.append(ts.getText(document));
fis.close();
document.close();
return content.toString().trim();
}

关键词查询(Search.java)

建立好索引后,就可以利用索引进行关键词查询。创建分析器Analyze,采用QueryParser实现模糊查询。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public static ArrayList<String> run(String indexPath, String queryVal) throws Exception {
ArrayList<String> list = new ArrayList<String>();
String field="contents";
TopDocs docs;
ScoreDoc sdoc[] = null;
IndexSearcher is;
Analyzer analyzer;
QueryParser parser;
Query query;
Document doc = null;
try{
IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(indexPath)));
is=new IndexSearcher(reader);
analyzer = new StandardAnalyzer();
parser = new QueryParser(field, analyzer);
query=parser.parse(queryVal);
docs=is.search(query, 10);
sdoc=docs.scoreDocs;
for(int i=0;i<sdoc.length;i++){
doc = is.doc(sdoc[i].doc);
list.add(doc.get("path"));
}
}catch(Exception e){
e.printStackTrace();
System.exit(1);
}
return list;
}

高亮显示(Highlighter.java)

高亮显示技术,是搜索引擎常用到的一项重要技术。在搜索引擎开发中引入高亮显示技术,使搜索结果一目了然。
在Lucene5.X的Highlighter包中提供了一个简单的Highlighter功能,PostingsHighlighter。实现步骤为,创建PostingsHighlighter对象,创建对象查询结果,获取查询结果,获取该查询结果所对应的高亮snippets。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static String[] run(String indexPath, String queryVal) throws Exception{
String field="contents";
TopDocs docs;
IndexSearcher is;
Analyzer analyzer;
QueryParser parser;
Query query;
String highlights[] = null;
try{
IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(indexPath)));
is=new IndexSearcher(reader);
analyzer = new StandardAnalyzer();
parser = new QueryParser(field, analyzer);
query=parser.parse(queryVal);
docs=is.search(query, 10);
PostingsHighlighter highlighter = new PostingsHighlighter();
highlights = highlighter.highlight("contents", query, is, docs, 3)
}catch(Exception e){
e.printStackTrace();
System.exit(1);
}
return highlights;
}

用户界面

用户界面采用B/S架构(浏览器/服务器模式)实现。服务器端使用Java Servlet技术完成,用户通过浏览器输入待查询关键词,服务器端返回搜索到的相关文档,客户端显示响应的查询结果的路径超链接,以及发现关键词的部分段落。点击超链接查看文档的详细内容。

用户主界面(index.jsp)

Index.jsp提供了一个查询初始界面,它接受用户所要查询的的关键词,并将这个词传给Result Servlet做下一步处理。

img

1
2
3
4
5
6
7
8
9
<body>
<div style="height:150px;"></div>
<form action="Result" method="post">
<div class="b_searchboxForm">
<input class="b_searchbox" id="sb_form_q" name="q" title="输入搜索词" value="" maxlength="100" type="search">
<input class="b_searchboxSubmit" id="sb_form_go" title="搜索" tabindex="0" name="go" value="Go" type="submit" >
</div>
</form>
</body>
查询结果(Result.java)

Result Servlet 使用request.getParameter(“q”);获取用户查询的关键词,将关键词作为参数送给Highlighter和Search并获取返回的相应结果集。使用一个循环将获取的信息返回给用户。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String sdir="E:\\Program\\woskspace EE\\SearchBox\\www2016";
String indexPath = "E:\\Program\\woskspace EE\\SearchBox\\index";
String search = request.getParameter("q");
String result[]=null;
ArrayList<String> path = new ArrayList<String>();
try {
// BuildIndex.run(sdir, indexPath);(只需在程序第一次运行时执行)
result = Highlighter.run(indexPath, search);
path=Search.run(indexPath, search);
} catch (Exception e) {
e.printStackTrace();
}
PrintWriter out= response.getWriter();

response.setContentType("text/html");
out.println("<html>");
out.println("<body style=\"background-color: #ffc;\">");
out.println("<div style=\"font-family: \"Segoe UI\",Segoe,Tahoma,Arial,Verdana,sans-serif ;font-size: 18px;\">");
out.println("<form name=\"input\" action=\"Result\" method=\"post\" >");
out.println("<input type=\"text\" name=\"q\" id=\"s\" style=\"width:550px; max-height:40px; height:45px; margin-top:3px>; border: 1px #e5e5e5 solid;\">");
out.println("<input type=\"submit\" value=\"Go\"style=\"width:42px; height:42px; border: 1px #ccc solid;\">");
out.println("<br><br>");
out.println("</div>");
out.println("<div>");
for(int i=0;i<path.size();i++){
out.println("<p font-size=\"20px\" >");
out.println("<a href='Document?path="+path.get(i)+"'>"+path.get(i)+"</a>");
out.println("</p>");
out.println("<p font-size=\"18px\">"+result[i]+"</p>");
out.println("<br>");
}
out.println("</div>");
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
}
文档内容显示(Document.java)

Document Servlet通过request.getParameter(“path”)获取Result Servlet提供的文档路径。创建Document对象,采用PDFTextStripper读取文档内容,PDDocumentInformation获取文档信息,如标题。按顺序输出文档内容。

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out= response.getWriter();
String path = request.getParameter("path");
out.println("<html>");
out.println("<body style=\"background-color: #ffc;\">");
out.println("<div style=\"font-family: \"Segoe UI\",Segoe,Tahoma,Arial,Verdana,sans-serif ;font-size: 18px;\">");
out.println("<form name=\"input\" action=\"Result\" method=\"post\" >");
out.println("<input type=\"text\" name=\"q\" id=\"s\" style=\"width:550px; max-height:40px; height:45px; margin-top:3px>; border: 1px #e5e5e5 solid;\">");
out.println("<input type=\"submit\" value=\"Go\"style=\"width:42px; height:42px; border: 1px #ccc solid;\">");
out.println("<br><br>");
out.println("</div>");
out.println("<div>");
PDDocument document = null;
File PDFpath= new File(path);
try
{
document=PDDocument.load(PDFpath);
// 读文本信息与内容
PDDocumentInformation info = document.getDocumentInformation();
PDFTextStripper stripper=new PDFTextStripper();
// 设置按顺序输出
stripper.setSortByPosition(true);
String content = stripper.getText(document);
out.println(info.getTitle());
out.println("<br><br><br>");
out.println(content);
}
catch(Exception e)
{
e.printStackTrace();
}
out.println("</div>");
out.println("</body>");
out.println("</html>");
document.close();
out.flush();
out.close();
}

Java接口与实现

发表于 2017-05-03 | 分类于 Java | 阅读次数

接口

接口包含接口声明和接口体

接口声明

接口使用关键字 interface 来声明接口。格式如下:

1
interfance 接口名字

接口体

接口体中包含常量的声明(没有变量)和抽象方法两部分。接口体中只有抽象方法没有普通方法,而且接口体中所有的常量的访问权限一定都是 public ,而且是 static 常量(允许省略 public 、 final 和 static 修饰符),所有的抽象方法的访问权限一定都是 public (允许省略 public abstract 修饰符)

1
2
3
4
5
interface Font{
public final static int max = 50; //等价于:int max = 50;
public abstract void add(); //等价于:void add();
public abstract float sum(float a, float b); //等价于:float sum(float a, float b);
}

接口实现

在Java中,接口由类来实现以便使用接口中的方法。一个类需要在类声明中使用关键字 implements 声明该类实现一个或多个接口。实现多个接口用逗号隔开接口名。

一个简单的实例 广告牌,展示多个公司广告词

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
interface Advertisement{
void showAdvertisement();
String getName();
}

class CompanyA implements Advertisement {
public void showAdvertisement() {
System.out.println("everything is possible!");
}

public String getName() {
return "coompanyA";
}
}
class CompanyB implements Advertisement{
public void showAdvertisement() {
System.out.println("just do youself!");
}

public String getName() {
return "companyB";
}
}

class AdvertisementBoard {
public void show(Advertisement advertisement) {
System.out.println(advertisement.getName()+" Advertisement :");
advertisement.showAdvertisement(); //接口回调
}
}

public class Interface {
public static void main(String[] args) {
AdvertisementBoard board = new AdvertisementBoard();
board.show(new CompanyA());
board.show(new CompanyB());
}
}

运行结果

1
2
3
4
coompanyA Advertisement
everything is possible!
companyB Advertisement
just do youself!

回朔法与n皇后问题

发表于 2017-04-30 | 分类于 算法设计与分析 | 阅读次数

回溯法

回溯法是应既带有系统性有带有跳跃性的搜索算法。它在包含问题的所有解的空间树中,按照深度优先的策略,从根节点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先的策略进行搜索。回溯法在用来求问题的所有解时要回溯到根,且根结点的所有子树都已被搜索遍才结束;而用来求问题的任一解时。只要搜索到问题的一个解就可以结束。这种以深度优先的方式系统地搜索问题的解的方法称为回溯法。

在应用回溯法解决问题时,首先应明确定义问题的解空间。问题的解空间应至少包含问题的一个(最优)解。在确定了解空间的组织结构后,回溯法从开始结点(根结点)出发,以深度优先的方式搜索整个解空间。这个开始结点就成为一个活结点,同时也成为当前的扩展结点。在当前的扩展结点处,搜索向纵深方向移至一个新结点。这个新结点就成为一个新的活结点,并成为当前的扩展结点。如果在当前 扩展结点处不能再向纵深方向移动,则当前的扩展结点就成为死结点。此时,应回溯(往回移动)至最近的一个活结点处,并使这个活结点成为当前的扩展结点。回溯法即以这种工作方式递归地在解空间中搜索,直到找到所要求的解或解空间中已无活结点为止。

n皇后问题

n皇后问题来源于国际象棋的一个问题。n皇后问题要求在一个n × n 格的棋盘上放置n个皇后,使得他们彼此不受攻击。按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的任何棋子。因此,n皇后问题等价于在一个n × n 格的棋盘上放置n个皇后,使得任意两个皇后不能被放在同一行或同一列或同一斜线上。

求解过程从空棋盘开始,设在第1行至第m行都正确的放置了m个皇后,再在第m+1行上找合适的位置放置第m+1个皇后,直到在第n行也找到合适的位置放置第n个皇后,就找到了一个解。接着改变第n行上皇后的位置,希望获得下一个解。另外,在任一行上有n种可能的位置。开始时位置在第1列,以后改变时,顺次选择第2列、第3列…、第n列。当n列也不是一个合理的位置时,就要回溯,去改变前一行的位置。

C代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <stdio.h>
#include <math.h>
#define N 4

/************************************************************************/
/* pos:一维数组,pos[i]表示第i个皇后放在第i行的具体位置 */
/* count:统计放置的方案数 */
/* N:皇后数 */
/* i,j,k:变量 */
/************************************************************************/

/*判断第k个皇后是否与前面皇后冲突*/
int IsPlase(int pos[],int k){
int i;
for (i = 1; i < k; i++){
if (pos[i]==pos[k] || fabs(i-k)==fabs(pos[i]-pos[k]))
{
return 0;
}
}
return 1;
}

int main(){

int i, j, count = 1;
int pos[N + 1];
/*初始化位置*/
for (i = 1; i <= N;i++)
{
pos[i] = 0;
}
j = 1;
while (j >= 1){
pos[j] = pos[j] + 1;
/*尝试摆放第j个皇后*/
while (pos[j] <= N && IsPlase(pos,j)==0)
{
pos[j] = pos[j] + 1;
}
/*得到第一个摆放方案*/
if (pos[j]<=N && j==N )
{
printf("方案%d ", count++);
for (i = 1; i <= N;i++)
{
printf("%d", pos[i]);
}
printf("\n");
}

/*考虑下一个皇后*/
if (pos[j]<=N && j<N)
{
j = j + 1;
}
else
{
pos[j] = 0;
j = j - 1;
}
}
return 0;
}

线性表的链式存储的基本操作

发表于 2017-04-23 | 分类于 C | 阅读次数
  1. 线性表的链式存储是用结点来存储数据元素,基本结点的结构为
数据域 指针域

其中,数据域用于存放存储数据元素的值,指针域存储当前元素的直接前驱或者直接后继的位置信息,指针域中的信息称为指针(或链)。

设线性表中的元素是整形,则单链表节点类型的定义为:

1
2
3
4
5
typedef struct Node
{
int data; /*节点的数据域*/
struct Node *next; /*节点的指针域*/
}Node, *LinkList;
  1. 在链式存储结构下进行插入
    在单链表中p所指结点后插入新元素结点s(s所指结点已生成),基本步骤如下:
1
2
s->next=p->next;
p-next=s;

即先将p所指结点的后继结点指针赋给s所指的结点的指针域,然后将p所指的结点的指针域修改为s所指的结点

  1. 在链式存储结构下进行删除
    在单链表中删除p结点所指结点的后继结点,基本步骤如下:
    1
    2
    3
    s=p->next;
    p->next=s->next; /*或者p->next=p->next->next;*/
    free(s);

先令临时指针s指向待删除的结点,然后修改p所指结点的指针域为指向p所指结点的后继的后继结点,从而将待删除结点从链表中删除,最后释放s所指的结点的空间

  1. 单链表的创建、输出、查询、插入、删除运算的实现过程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#include <stdio.h>

typedef struct Node
{
int data;
struct Node *next;
}Node, *LinkList;

//链表初始化
LinkList Init_LNode()
{
Node *L;
L = (LinkList)malloc(sizeof(Node));
if (L == NULL)
{
printf("初始化失败!\n");
exit(-1);
}
L->next = NULL;
return L;
}

//头插法
LinkList Creat_List(Node *L)
{
int i, num, n;
Node *p;
printf("请输入要输入的元素个数:n = ");
scanf("%d", &n);
for (i = 0; i < n; i++)
{
printf("请输入第%d个数:", i + 1);
scanf("%d", &num);
p = (LinkList)malloc(sizeof(Node));
p->data = num;
p->next = L->next;
L->next = p;
}
return L;
}

//单链表的查找,某元素是由存在链表中
LinkList Find_List(Node *L, char e){
Node *p;
p = L;
int i=0;
while (p && p->next)
{
p = p->next;
i++;
if (p->data == e)
{
return i;
}
}
return 0;
}

//单链表查找,某位置是否存在元素
LinkList Find(Node *L, int k)
{
Node *p;
int i;
i = 1;
p = L->next;
while (p && i < k)
{
p = p->next;
i++;
}
if (p && i == k)
{
return p;
}
return 0;
}

//单链表的插入
int Insert_List(Node *L, int k, int e){
Node *p, *s;
if (k == 1)
{
p = L;
}
else
{
p = Find(L, k - 1);
}
if (!p)
{
return 0;
}
s = (LinkList)malloc(sizeof(Node));
if (!s)
{
return 0;
}
s->data = e;
s->next = p->next;
p->next = s;
return 1;
}

//单链表的删除
int Delete_List(Node *L, int k)
{
Node *p, *s;
int e;
if (k == 1)
{
p = L;
}
else
{
p = Find(L, k - 1);
}
if (!p || !p->next)
{
return 0;
}
s = p->next;
p->next = s->next;
e = s->data;
free(s);
return e;
}

//输出单链表元素
PrintResult(Node *L)
{
Node *p;
p = L;
while (p && p->next)
{
p = p->next;
printf("%d", p->data);
}
printf("\n");
}

//主程序
int main(){

Node *L;
L = Init_LNode();
L = Creat_List(L);

printf("****************************************\n");
printf("**** 1.查看链表元素 *****\n");
printf("**** 2.查询某元素是否存在 *****\n");
printf("**** 3.查询某位置是否存在元素 *****\n");
printf("**** 4.插入元素 *****\n");
printf("**** 5.删除元素 *****\n");
printf("**** 0.退出程序 *****\n");
printf("****************************************\n");

char ch;
printf("\n是否继续?(Y/N or y/n)");
scanf("%s", &ch);
while (ch=='y' || ch=='Y')
{
int num;
printf("请输入所需操作:(0-5)");
scanf("%d", &num);

int i, k, e;
Node *p;
switch (num)
{
case 1:
PrintResult(L);
break;
case 2:
printf("请输入所需查询的元素:");
scanf("%d", &e);
k = Find_List(L, e);
if (k)
{
printf("该元素所在位置为%d!\n",k);
}
else
{
printf("所查询元素不存在!\n");
}
break;
case 3:
printf("请输入想要查看的位置:");
scanf("%d", &k);
p = Find(L, k);
if (p)
{
printf("该位置存在元素为%d\n", p->data);
}
else
{
printf("该位置为空!\n");
}
break;
case 4:
printf("请输入插入元素的位置:");
scanf("%d", &k);
printf("\n请输入插入元素:");
scanf("%d", &e);
i = Insert_List(L, k, e);
if (i)
{
printf("插入成功!\n");
}
else
{
printf("插入失败!\n");
}
break;
case 5:
printf("请输入删除的元素的位置:");
scanf("%d", &k);
i = Delete_List(L, k);
if (i)
{
printf("删除成功,删除元素为%d\n",i);
}
else
{
printf("删除失败!\n");
}
break;
case 0:
exit();
break;
default:
break;
}

printf("\n是否继续?(Y/N or y/n)");
scanf("%s", &ch);
}

return 0;
}

使用正则表达式对信息进行提取

发表于 2017-04-21 | 分类于 Java | 阅读次数

正则表达式通过按一定的语法规则在一段文字中进行匹配,然后返回匹配结果。

匹配类型:

在一段文本中发现石否包含某个子串
抽取出符合正则表达式语法的子串
对符合正则表达式的子串进行替换
返回一个布尔值,判断是否匹配

在 Java 中使用正则表达式的方法如下:
Java 中关于正则表达式有两个类,一个接口和一个异常

1
2
3
4
Java.util.regex.Pattern;
Java.util.regex.Matcher;
Java.util.regex.MatchResult;
Java.util.regex.PatternSyntaxException;

一个 Pattern 对象是一个编译的正则表达式,可以用于任何字符串。 一个 Matcher 对象
是一个单个的用于一个特别目标字符串的实例。 MatchResult 封装了一次成功匹配的数
据。
Pattern.compile()方法将一个字符串编译成正则表达式。 即得到一个 Pattern 对象。

1
2
3
4
5
6
7
8
9
String regex="(<String?>.+?</String?>)";
String str="<id>4654165ashdjfkl</id><String>QWEHASOIUASC</String>";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
String s;
if(m.find()){
s = m.group(1);
System.out.println(s);
}

上例中,字符串 regex 是我们写好的正则表达式的字符串。 变量 str 是待匹配的字符串。
Pattern p = Pattern.compile(regex);
将正则表达式字符串编译,得到一个 Pattern 对象。

Pattern 对象下的 matcher()方法是使用当前编译的正则表达式去匹配字符串,然后得到一个 Matcher 对象。 Matcher 对象的 find()方法判断是否匹配成功。 正则表达式的一次匹配结果可以包含多个子串,用 Matcher 对象的 group 方法来获得匹配结果的多个子串。 其参数是一次匹配中第几个匹配的子串。如上图是一次匹配中的第一个匹配的子串。 (注:一个正则表达式可以从匹配的字符串中抽取多个子串,其中子串用括号来表示,如上例中有一对括号,因此就有一个匹配的子串。 )

正则表达式

一些 meta characters:
(1)^ 开始字符。例如,^cat 表示匹配一段文字。 这一段文字如果以‘cat’开始,则可以匹配

(2)$ 结束字符。例如,cat$,表示匹配以 cat 结尾的一段文字

(3)[ ] 字符类,列举想要匹配的字符。例如,gr[ea]y,表示匹配含有 grey 或gray 子串的文字

(4)- 在字符类内部使用- 表示范围。例如,[0123456789abcdEFGH]可以写成[0-9a-dE-H]。 注:“-”仅仅在字符类内部是 meta character。

(5)在字符类内部使用^表示非。[^1-6]表示匹配一个字符不是 1 到 6 的。

(6). 匹配任意字符。但在字符类[.]内的“.”就是它的字面意思而不是特殊字符。例如正则表达式 03[.]16[.]76 可以匹配 03.16.76,03\16\76,03.16\76,03\16.76。再看正则表达式 “ [0-9].[0-9]” ,表达的是匹配包含下来子串的字符串“ 数字任意字符数字” 。 即子串的第一个字符是数字,第二个字符是任意字符,第三个字符是数字

(7)| 表示或。例如,Bob|Robert 表示匹配 Bob 或 Robert。正则表达式 Gr[ea]y 可以写成 grey|gray。 也可以写成 gr(e|a)y。但 gr[e|a]y 中的“|”不是特殊字符,是其字面意思。 gr(e|a)y 中括号约束了替换的范围,即两个字符 e 和 a 的替换。

(8)? 表示选择,即在?前面的字符是可选择的。colou?r 即匹配 color 或者 colour。4(th)?表示匹配 4 或者 4th。此处括号对可选择的多个字符做了限制

(9)+ 表示一个或多个立即跟随的字符。例如,[0-9]+表示任意长的数字,012,,91 等

(10)\ 表示后面跟的字符是字面含义,而不是特殊字符。例如,ega.att.com。此处的“.”不是特殊字符而是 literal。 匹配 ega.att.com。

(11){min,max} 定义匹配的范围。例如, [a-z]{1,3}表示字母 a-z 可以出现一次,最多三次。

(12)( ) 有两种含义,一是表示限定范围;二是,当从字符串中取出子串时,括号规定了要提取的子串。

(13)> 特殊字符:

\d 表示数字
\D 表示非数字,等于[^\d]
\w 等同于[a-zA-Z0-9]
\W 等同于 [^\w]
\s 空白符等同于[\f\n\r\t\v]
\S 非空白符
\b 匹配一个 backspace 或 tab 字符

例:

(1)

1
2
3
4
5
String regex="q[^u]";
String str="Iraq";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
System.out.println(m.find());

结果是false。该正则表达式,要匹配的字符串包含字符q,并且后面必须跟着一个不是u的字符。

(2)

1
2
3
4
5
String regex="q[^u]";
String str="Qantas";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
System.out.println(m.find());

结果还是false。应为正则表达式对大小写敏感。如果想要消除这种敏感,编译正则表达式时使用

1
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);

(3)
两个正则表达式
^From|Subject|Date:
^(From|Subject|Date):
匹配结果有什么不同

1
2
3
4
5
6
7
8
9
String regex="^From|Subject|Date:";
String regex1="^(From|Subject|Date):";
String str="hello Subject: dallas";
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
attern p1 = Pattern.compile(regex1, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(str);
Matcher m1 = p1.matcher(str);
System.out.println(m.find());
System.out.println(m1.find());

结果是

1
2
true
false

这是因为,第一个正则表达式^From|Subject|Date: 表示匹配^From(被匹配的字符串必须以 From 开头)或者Subject (包含子串 Subject) 或者Date:(包含字符串Date:)。第二个正则表达式^(From|Subject|Date):表示匹配的字符串必须以From:或者Subject: 或者Date:开头。

(4)

1
2
3
4
5
String regex="^h.+d$";
String str="hello world";
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(str);
System.out.println(m.find());

结果是true。该正则表达式匹配以h开头,d结尾的字符串。.+表示匹配任意多个字符

(5)

1
2
3
4
5
String regex="hello\\.world";
String str="Hi, hello.world, Yes";
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(str);
System.out.println(m.find())

这段代码中,要匹配一个子串“hello.world”。 因为正则表达式中“.”是特殊字符。因此要匹配该子串,我们写的正则表达式应该是“hello.world”,这里的“\”表示后面的“.”是其字面意思,不是特殊字符。而在 java 中“\”又是特殊字符,我们就再加上一个“\”字符。因此得到了最终的正则表达式”hello\.world”。

(6)我们要提取字符串“ price is 34$, today is April 12” 中描述的价格。

1
2
3
4
5
6
7
8
9
String regex="([0-9]+)\\$";
String str="price is 34$, today is April 11";
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(str);
String s;
if(m.find()){
s=m.group(1);
System.out.println(s);
}

美元符号$在正则表达式中是特殊字符,当前的例子中,文本中包含了美元符号,因此在写正则表达式时,需要在它的前面加上“\”表示其后的美元符号不是特殊字符。另外,括号的作用在于指示这是要提取出的子串。 因此程序运行结果是 34。

(7)匹配字符串“ price is 34$, today is April 12” 中的所有数字,即 34 和 11

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
String regex="([0-9]+)";
String str="price is 34$, today is April 11";
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher m;
String s;
Integer location=0;
while(location<str.length()){
m = p.matcher(str);
if(m.find(location)){
s=m.group(1);
System.out.println(s);
location=m.end();
}else{
break;
}
}

匹配的结果中包含了匹配的子串的起始位置和结束位置,可以用 Matcher 对象的 start()方法和 end()方法来获得。 定义一个 Integer 类型的变量 location,它记录每趟循环中匹配到的子串的结束位置。find(location)方法,表示从当前 location 的位置去寻找匹配的子串。因此在 while 循环中多次去匹配字符串,发现字符串多个与正则表达式匹配的子串。

(8)对于包含小数点的数字的提取

1
2
3
4
5
6
7
8
9
10
String regex="([0-9]+\\.[0-9]+)";
String str="price is 343.4$, today is April 11";
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher m;
String s;
m = p.matcher(str);
if(m.find()){
s=m.group(1);
System.out.println(s);
}

字符串中混合了小数和整数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
String regex="([0-9]+(\\.[0-9]+)?)";
String str="price is 343.4$, today is April 11";
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher m;
String s;
Integer location=0;
while(location<str.length()){
m = p.matcher(str);
if(m.find(location)){
s=m.group(1);
System.out.println(s);
location=m.end();
}else{
break;
}
}

该正则表达式中有两对括号,其中一对嵌入在另一对中。 里面的那一对后面有个?,是用来指示括号里面的内容是“可选择的”。 匹配的子串是外面的那一对括号。

(9)提取出时间

1
2
3
4
5
6
7
8
9
10
String regex="([0-9]?[0-9]:[0-9][0-9]\\s(am|pm)?)";
String str="It is 9:21 am";
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher m;
String s;
m = p.matcher(str);
if(m.find()){
s=m.group(1);
System.out.println(s);
}

贪婪模式和非贪婪模式

贪婪模式,正则表达式默认的是最大匹配。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
String regex="<[a-zA-Z]+>.+</[a-zA-Z]+>";
String str="<p>hello</p><div>world</div>";
Pattern p = Pattern.compile(regex);
Matcher m;
String s;
Integer location=0;
while(location<str.length()){
m = p.matcher(str);
if(m.find(location)){
s=m.group(0);
System.out.println(s);
location=m.end();
}else{
break;
}
}

结果是

1
<p>hello</p><div>world</div>

使用非贪婪模式,正则表达式中的“*”或“+”后加上一个 ?符号,称为惰性符号<[a-zA-Z]+>.+?</[a-zA-Z]+>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
String regex="<[a-zA-Z]+>.+?</[a-zA-Z]+>";
String str="<p>hello</p><div>world</div>";
Pattern p = Pattern.compile(regex);
Matcher m;
String s;
Integer location=0;
while(location<str.length()){
m = p.matcher(str);
if(m.find(location)){
s=m.group(0);
System.out.println(s);
location=m.end();
}else{
break;
}
}

结果是

1
2
<p>hello</p>
<div>world</div>

SAS的基本应用

发表于 2017-04-15 | 分类于 数据挖掘 | 阅读次数

关于SAS的基本应用

不同版本的SAS,使用规则会有所不同

定义逻辑库 data (链接d盘的data文件夹下)

1
libname data 'D:DATA\';

删除逻辑库 Data

1
libname data clear;

变量的命名

最多32个字符长,第一个字符必须是字母或下划线,不能有空格。不能包含特殊字符(如¥,@,#)

SAS运算符:

不等于: ~=、 <>、ne
等于: eq、=
大于等于:>=、ge
小于等于:<=、le
大于:>、gt
小于:<、lt
逻辑运算符:&、| ~
连接符:||

设置当前逻辑库

1
options user=data;

数据步

一般形式:

1
2
3
4
DATA 数据集;
语句;
......
RUN;

过程步

一般形式

1
2
3
4
5
proc 过程名 DATA=分析数据集 [选项];
过程语句 / [选项]
过程语句 / [选项]
......
run;

控制语句

1
2
3
4
5
6
7
8
9
if 条件 then 语句; else 语句;

do 变量=初值 to 终值 by 步长;
语句;
end;

do while (条件); 或者 do until (条件);
语句;
end;

对表格进行排序

1
2
3
4
5
6
7
8
9
降序排列
proc sort data = student;
by descending age;
run;

升序排列
proc sort data=student;
by no;
run;

数据合并

纵向合并或数据集复制

1
2
3
data table;
set table1 table2;
run;

横向合并(先对要合并的数据集按相同的变量排序)

1
2
3
4
data table;
merge table1 table2;
by no;
run;

如果table1与 table2的变量不完全相同,需要在结果中只包含共同的变量:

1
2
3
4
5
6
7
8
9
data table; 
set table1(keep=保留变量名列表)
table2 (keep=保留变量名列表);
run;
或:
data table;
set table1(drop=去除变量名列表)
table2 (drop=去除变量名列表);
run;

如果需要在结果中只包含部分观测:

1
2
3
4
data table; 
set table1(where=(条件))
table2 (where=(条件));
run;

利用SQL过程实现数据预处理

1
2
3
4
5
6
7
8
proc sql;
create table …;
alter table … add|drop|modify…;
update … set …;
insert into …..;
delete from … where …;
seclet …;
quit;

数据导入

1
2
3
4
5
6
proc import out = data.table
dtafile='d:\data\table.xls'
dbms=excel replace;
sheet='sheet1$';
getname=yes;
run;

数据集导出

1
2
3
4
5
proc export data=table
outfile='d:\data\table1.xls'
dbms=excel replace;
sheet='table1';
run;

统计值

1
2
3
proc freq data=table;
table age;
run;

使用SuperScan对目标主机进行端口扫描/网络服务扫描

发表于 2017-04-10 | 分类于 网络安全 | 阅读次数

软件介绍

SuperScan是由Foundstone公司开发的一款免费的扫描工具,功能强大,扫描速度快。

软件下载地址

下面开始介绍软件的使用
这是一款绿色软件,不需要安装,解压后直接运行可执行文件。(需要以管理员身份运)

运行后的初始界面

扫描(scan)

对局域网中的主机进行扫描

在“start IP” 填入想要扫描的起始IP地址,在“End IP”填入结束扫描的IP地址。单击箭头按钮将目标IP地址范围添加到扫描地址池中,运行端口扫描。扫描结束后,可以点击“查看HTML结果”(View HTNL Results),在浏览器器中查看本次扫描结果。出现TCP端口扫描结果为0,是因为由于主机禁止了扫描器的ICMP扫描响应,因此需要修改对主机的扫描方式。下面是一次扫描结果

从结果中可以看出该网络中共有14台活动的主机,其中192.168.191.2开放了7个TCP端口:81、135、139、445、1025、3389、9090。主机192168.191.3开放了8个TCP端口:21、80、135、139、445、1025、1433、3389。

主机和服务器扫描设置(Host and Service Discover)

如果扫描结果不满足需求,这就需要对扫描进行一些修改。取消“查找主机”复选框。选中“UDP端口扫描”,将UDP扫描类型设置为Data。选中“TCP端口扫描”,将TCP扫描类型设置为直接连接(Connect)。

 photo SuperScan03_zpse7ebeldg.png

扫描选项(Scan Options)

对扫描进程进行进一步的控制。可以设置扫描过程中主机和通过审查的服务数,主机名的解析数,标志获取。标志获取(Banner Grabbing)表示在规定的时间内是否收到回应。

工具(Tools)

SuperScan的Tools可以较快的得到关于一个主机的信息。正确的输入主机名或IP或默认的连接服务器。选择想要进行的操作,相关信息就会在右边的文本框中显示出来。

Windows枚举(Windows Enumeration)

根据需要枚举出想要查看的Windows主机的相关信息

Windows下搭建Node.js + Github个人博客

发表于 2017-04-07 | 分类于 博客相关 | 阅读次数

1.搭建Node.js环境

Node.js下载地址

安装过程其实并不复杂,执行安装文件后,一直选择 next 就可以了,至于安装路径,根据自己的情况选。下面是步骤图,版本不一样,图可能有些不一样。

安装完成后,检查组件是否安装成功。在命令提示符中输入

1
2
node -v
npm -v

出现相应的版本信息就表示安装成功。

2.搭建Git环境

Git下载地址

git的安装过程同样很简单,不需要修改什么地方。下载是安装过程图。

安装完成后,检查组件是否安装成功。在命令提示符中输入

1
git --version

出现相应的版本信息表上安装成功。

3.注册github账号

如果已经有了github账号就不用注册了,直接创建仓库就好。

注册账号

输入账号,邮箱与密码,点击注册

注册成功后进入这个页面,选择 free, 点击continue

进入这个页面,可以不选,直接 submit

认证邮箱,登录邮箱确认注册信息,确认之后就可以开始创建仓库了

4.创建仓库

选择 star a project

仓库名与github账号名对应。规则:name.github.io其,他的可以选择性填写 create repository

开启gh-pages功能,点击右上角的 Settings

向下拖动到GitHub Pages,如下图,找到Source 选择分枝并保存,系统会提示name.github.io可以访问了。可以访问后github的配置就结束了。

5.安装Hexo

选择一个地方创建文件夹,存放Hexo。进入Hexo文件夹,右键,选择git bash,输入

1
npm install -g hexo

出现WARN可不用理会,继续输入以下命令

1
npm install hexo --save

安装完成后,输入命令,验证是否安装成功

1
hexo -v

6.本地运行Hexo

  • 初始化
1
hexo init
  • 安装生成器
1
npm install
  • 运行Hexo
1
2
hexo -g
hexo s

打开浏览器,输入localhost:4000,就可以在本地看到个人博客了

如果浏览器一直没有加载出内容,有可能是端口被占用了,改个端口试试

1
hexo s -p 5000

7.将Hexo与Github page 联系起来

配置Git个人信息

如果之前已近配置过个人信息就不用配置了

1
2
git config --global user.name "GitHub用户名"
git config --global user.email "登录邮箱"

生成密钥

  • 检查是否已有SSH Key
1
cd ~/.ssh

提示:No such file or directory 说明你是第一次使用git

  • 生成新的SSH Key
1
ssh-keygen -t rsa -C "邮箱"

系统会要求你输入密码,可以输入密码,也可以为空。为空提交项目时则不用输密码

添加SSH Key到Github

在本地设置SSH Key后,需要添加到Github上,已完成SSH连接的设置。

  • 打开本地C:\用户\username.ssh\id_rsa.pub文件(username是你的用户名)。这个文件就是之前生成的SSH Key,默认是隐藏文件夹,需设置显示隐藏文件夹。复制文件内容

  • 登录github网站,点击右上角用户的下三角下的Settings—->SSH Public keys—->add another public keys。

  • 将复制的密钥粘贴到文本框中,点击add key 就可以了。

  • 测试

输入命令

1
ssh -T git@github.com

可能会要求输入yes或no,输入yes就好,然后就会出现成功的信息。

8.配置Deployment

在_config.yml文件中,找到Deployment, 然后如下修改

1
2
3
4
deploy:
type: git
repo: https://github.com/name/name.github.io.git
branch: master

9.添加Hexo git插件

1
2
npm install hexo-deployer-git --save
hexo deploy(可以缩写成d)

未安装此插件,在执行 hexo delop时会提示 ERROR Deployer not found: git

到这基本配置应该就结束了,至于主题就选择自己喜欢的去配就好了。如果有什么不对的地方可以指出来,就酱(≧∀≦)ゞ

图的顺序不知道有没有搞错(:зゝ∠)

Hexo的Next主题相关配置

发表于 2017-04-05 | 分类于 博客相关 | 阅读次数

Next主题相关配置

应该是官方网页吧,基本配置都有 ^_^

1…345
篱笆外小雨

篱笆外小雨

刚刚好^_^

41 日志
22 分类
26 标签
RSS
© 2018 篱笆外小雨
由 Hexo 强力驱动
主题 - NexT.Mist