如何使用Java将bash脚本分解为最小的工作块
我想编写一个Java方法,将bash脚本读入单个字符串对象,然后将该字符串分解为最小的字符串命令数组,这样我就可以一次执行一个命令。我遇到的问题是,我需要保持块语句(例如if和while以及输入重定向)完好无损,也就是说,不要进一步分解它们 例如,下面的bash脚本:如何使用Java将bash脚本分解为最小的工作块,java,regex,bash,Java,Regex,Bash,我想编写一个Java方法,将bash脚本读入单个字符串对象,然后将该字符串分解为最小的字符串命令数组,这样我就可以一次执行一个命令。我遇到的问题是,我需要保持块语句(例如if和while以及输入重定向)完好无损,也就是说,不要进一步分解它们 例如,下面的bash脚本: ./configure --sbindir=/lib/security \ --docdir=/usr/share/doc/Linux-PAM-1.1.3 \ --enable-re
./configure --sbindir=/lib/security \
--docdir=/usr/share/doc/Linux-PAM-1.1.3 \
--enable-read-both-confs &&
make
install -v -m755 -d /etc/pam.d &&
cat > /etc/pam.d/other << "EOF"
auth required pam_deny.so
account required pam_deny.so
password required pam_deny.so
session required pam_deny.so
EOF
rm -rfv /etc/pam.d
make install &&
chmod -v 4755 /lib/security/unix_chkpwd &&
mv -v /lib/security/pam_tally /sbin &&
mv -v /lib/libpam{,c,_misc}.la /usr/lib &&
sed -i 's| /lib| /usr/lib|' /usr/lib/libpam_misc.la &&
if [ -L /lib/libpam.so ]; then
for LINK in libpam{,c,_misc}.so; do
ln -v -sf ../../lib/$(readlink /lib/${LINK}) /usr/lib/${LINK} &&
rm -v /lib/${LINK}
done
fi
echo done
这可以使用正则表达式或使用Java的其他方法来实现吗
即使是一些伪代码也是受欢迎的。正则表达式对于这一点是不够的,您需要正确地解析语法,以获得可靠工作的东西 解析shell脚本一点也不容易(AFAIK没有正式语法) 一旦完成了解析,执行“逐块”通常不会起作用。您需要跟踪环境变量更改、当前目录更改等
话虽如此,你有没有看过这样的东西?你真的需要一个解析器 看看这个项目,它听起来和你想做的非常相似
他们似乎已经构建了您所需的所有基本组件 这就是我目前得到的。我还没有完全测试过它
String compoundCommand = null;
ArrayList<String> commandList = new ArrayList<String>();
String list = "";
int count = 0;
ArrayList<String> splitBashScript(String script) {
script = script.replaceAll("\\\\\n", "");
script = script.replaceAll("([^;]);([^;])", "$1\n$2");
String[] lines = Pattern.compile("[ \t]*\n", Pattern.MULTILINE).split(script);
String delimiter = null;
for (String line : lines) {
if (!line.isEmpty()) {
if (compoundCommand == null) {
if (line.matches(".*<<.*")) {
compoundCommand = "here";
delimiter = line.replaceFirst(".*<< *", "").replaceAll("\"", "");
list += line;
} else if (line.matches("[ \t]*for[ \t]*.*")) {
compoundCommand = "for";
count++;
list += line;
} else if (line.matches("[ \t]*select[ \t]*.*")) {
compoundCommand = "select";
count++;
list += line;
} else if (line.matches("[ \t]*case[ \t]*.*")) {
compoundCommand = "case";
count++;
list += line;
} else if (line.matches("[ \t]*if[ \t]*.*")) {
compoundCommand = "if";
count++;
list += line;
} else if (line.matches("[ \t]*while[ \t]*.*")) {
compoundCommand = "while";
count++;
list += line;
} else if (line.matches("[ \t]*until[ \t]*.*")) {
compoundCommand = "until";
count++;
list += line;
} else if (list.isEmpty()) {
commandList.add(line.replaceFirst("[ \t]*&&$", ""));
}
} else if (compoundCommand.equals("here")) {
list += "\n" + line;
if (line.matches(delimiter)) {
compoundCommand = null;
commandList.add(list.replaceFirst("[ \t]*&&$", ""));
list = "";
}
} else if (compoundCommand.equals("for")) {
compound(line, "(for|select|while|until)", "done");
} else if (compoundCommand.equals("select")) {
compound(line, "(for|select|while|until)", "done");
} else if (compoundCommand.equals("case")) {
compound(line, "case", "esac");
} else if (compoundCommand.equals("if")) {
compound(line, "if", "fi");
} else if (compoundCommand.equals("while")) {
compound(line, "(for|select|while|until)", "done");
} else if (compoundCommand.equals("until")) {
compound(line, "(for|select|while|until)", "done");
}
}
}
return commandList;
}
void compound(String line, String start, String end) {
list += "\n" + line;
if (line.matches("[ \t]*" + start + "[ \t]*.*")) {
count++;
}
if (line.matches("[ \t]*" + end + "[ \t]*.*")) {
count--;
}
if (count == 0) {
compoundCommand = null;
commandList.add(list.replaceFirst("[ \t]*&&$", ""));
list = "";
}
}
String compoundCommand=null;
ArrayList commandList=新建ArrayList();
字符串列表=”;
整数计数=0;
ArrayList splitBashScript(字符串脚本){
script=script.replaceAll(“\n”,”);
script=script.replaceAll(([^;]);([^;]),“$1\n$2”);
String[]line=Pattern.compile(“[\t]*\n”,Pattern.MULTILINE).split(脚本);
字符串分隔符=null;
用于(字符串行:行){
如果(!line.isEmpty()){
if(compoundCommand==null){
如果(line.matches)(".*我的代码的执行部分已经很好地工作了,因为环境变量更改、当前目录更改等都得到了处理。这一切都是在执行bash的单个进程下完成的,但是在不存在bash进程的情况下,它还具有在每个命令后返回状态代码的附加功能。这将分解为更小的块s是个不错的选择。我访问了jbash网站。我不确定这是否符合我的总体目标。谢谢。
make
install -v -m755 -d /etc/pam.d
cat > /etc/pam.d/other << "EOF"
auth required pam_deny.so
account required pam_deny.so
password required pam_deny.so
session required pam_deny.so
EOF
rm -rfv /etc/pam.d
make install
chmod -v 4755 /lib/security/unix_chkpwd
mv -v /lib/security/pam_tally /sbin
mv -v /lib/libpam{,c,_misc}.la /usr/lib
sed -i 's| /lib| /usr/lib|' /usr/lib/libpam_misc.la
if [ -L /lib/libpam.so ]
then
for LINK in libpam{,c,_misc}.so; do
ln -v -sf ../../lib/$(readlink /lib/${LINK}) /usr/lib/${LINK} &&
rm -v /lib/${LINK}
done
fi
echo done
String compoundCommand = null;
ArrayList<String> commandList = new ArrayList<String>();
String list = "";
int count = 0;
ArrayList<String> splitBashScript(String script) {
script = script.replaceAll("\\\\\n", "");
script = script.replaceAll("([^;]);([^;])", "$1\n$2");
String[] lines = Pattern.compile("[ \t]*\n", Pattern.MULTILINE).split(script);
String delimiter = null;
for (String line : lines) {
if (!line.isEmpty()) {
if (compoundCommand == null) {
if (line.matches(".*<<.*")) {
compoundCommand = "here";
delimiter = line.replaceFirst(".*<< *", "").replaceAll("\"", "");
list += line;
} else if (line.matches("[ \t]*for[ \t]*.*")) {
compoundCommand = "for";
count++;
list += line;
} else if (line.matches("[ \t]*select[ \t]*.*")) {
compoundCommand = "select";
count++;
list += line;
} else if (line.matches("[ \t]*case[ \t]*.*")) {
compoundCommand = "case";
count++;
list += line;
} else if (line.matches("[ \t]*if[ \t]*.*")) {
compoundCommand = "if";
count++;
list += line;
} else if (line.matches("[ \t]*while[ \t]*.*")) {
compoundCommand = "while";
count++;
list += line;
} else if (line.matches("[ \t]*until[ \t]*.*")) {
compoundCommand = "until";
count++;
list += line;
} else if (list.isEmpty()) {
commandList.add(line.replaceFirst("[ \t]*&&$", ""));
}
} else if (compoundCommand.equals("here")) {
list += "\n" + line;
if (line.matches(delimiter)) {
compoundCommand = null;
commandList.add(list.replaceFirst("[ \t]*&&$", ""));
list = "";
}
} else if (compoundCommand.equals("for")) {
compound(line, "(for|select|while|until)", "done");
} else if (compoundCommand.equals("select")) {
compound(line, "(for|select|while|until)", "done");
} else if (compoundCommand.equals("case")) {
compound(line, "case", "esac");
} else if (compoundCommand.equals("if")) {
compound(line, "if", "fi");
} else if (compoundCommand.equals("while")) {
compound(line, "(for|select|while|until)", "done");
} else if (compoundCommand.equals("until")) {
compound(line, "(for|select|while|until)", "done");
}
}
}
return commandList;
}
void compound(String line, String start, String end) {
list += "\n" + line;
if (line.matches("[ \t]*" + start + "[ \t]*.*")) {
count++;
}
if (line.matches("[ \t]*" + end + "[ \t]*.*")) {
count--;
}
if (count == 0) {
compoundCommand = null;
commandList.add(list.replaceFirst("[ \t]*&&$", ""));
list = "";
}
}