Skip to content

Instantly share code, notes, and snippets.

@ShadowPower
Last active May 27, 2019 00:37
Show Gist options
  • Save ShadowPower/22cceef242fce65217eb7bf912806b99 to your computer and use it in GitHub Desktop.
Save ShadowPower/22cceef242fce65217eb7bf912806b99 to your computer and use it in GitHub Desktop.
有人说想要个拆分Shell命令和参数的工具,转义只需要支持\" \'
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
enum State {
NORMAL,SPACE,SINGLE,DOUBLE,ESCAPE
}
class Extractor {
private State state; // 当前状态
private String input; // 纸带
private int index; // 位置
private StringBuilder buffer; // 缓冲区
private List<String> result; // 运行结果
private State preState; // 转义之前的状态
// 初始化状态机
private Extractor(String input) {
state = State.NORMAL;
preState = State.NORMAL;
this.input = input;
index = 0;
buffer = new StringBuilder();
result = new ArrayList<>();
}
// 正常状态
private void normalState() {
switch (input.charAt(index)) {
case ' ':
state = State.SPACE;
result.add(buffer.toString());
buffer = new StringBuilder();
break;
case '\'':
state = State.SINGLE;
break;
case '\"':
state = State.DOUBLE;
break;
case '\\':
preState = state;
state = State.ESCAPE;
break;
default:
state = State.NORMAL;
buffer.append(input.charAt(index));
}
}
// 空格状态
private void spaceState() {
switch (input.charAt(index)) {
case ' ':
state = State.SPACE;
break;
case '\'':
state = State.SINGLE;
break;
case '\"':
state = State.DOUBLE;
break;
case '\\':
preState = state;
state = State.ESCAPE;
break;
default:
state = State.NORMAL;
buffer.append(input.charAt(index));
}
}
// 单引号状态
private void singleState() {
switch (input.charAt(index)) {
case '\'':
state = State.NORMAL;
break;
case '\\':
preState = state;
state = State.ESCAPE;
break;
case ' ':
case '\"':
default:
state = State.SINGLE;
buffer.append(input.charAt(index));
}
}
// 双引号状态
private void doubleState() {
switch (input.charAt(index)) {
case '\"':
state = State.NORMAL;
break;
case '\\':
preState = state;
state = State.ESCAPE;
break;
case ' ':
case '\'':
default:
state = State.DOUBLE;
buffer.append(input.charAt(index));
}
}
// 转义字符状态
private void escapeState() {
state = preState;
buffer.append(input.charAt(index));
}
// 运行
public static List<String> convert(String command) {
Extractor extractor = new Extractor(command);
for (int i = 0; i < command.length(); i++) {
// 走带
extractor.index = i;
// 触发状态
switch (extractor.state) {
case NORMAL:
extractor.normalState();
break;
case SPACE:
extractor.spaceState();
break;
case SINGLE:
extractor.singleState();
break;
case DOUBLE:
extractor.doubleState();
break;
case ESCAPE:
extractor.escapeState();
}
}
// 写入最后一个结果
extractor.result.add(extractor.buffer.toString());
// 如果引号未闭合
if (extractor.state == State.SINGLE || extractor.state == State.DOUBLE) {
System.out.println("检测到未闭合的引号,请检查该命令是否合法: " + extractor.input);
}
return extractor.result;
}
}
public class ShellArgs {
public static void main(String[] args) {
while (true) {
Scanner sc = new Scanner(System.in);
System.out.print("nindeDianNao:~ nin$ > ");
String command = sc.nextLine();
System.out.println(Extractor.convert(command));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment