Last active
May 27, 2019 00:37
-
-
Save ShadowPower/22cceef242fce65217eb7bf912806b99 to your computer and use it in GitHub Desktop.
有人说想要个拆分Shell命令和参数的工具,转义只需要支持\" \'
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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