我想编写一个Java方法,将一个bash脚本读入一个String对象,然后将该String拆分为最小的String命令数组,这样我就可以一次执行一个命令。我遇到的问题是我需要保持块语句(例如if和while以及输入重定向)完整,即不要进一步分解它们。
例如,以下bash脚本:
./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
我想以编程方式将其分解为
./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的其他方法吗?
即使是一些伪代码也是受欢迎的。
答案 0 :(得分:1)
正则表达式对此不够,您需要正确解析语法以获得可靠运行的东西。
解析shell脚本并不容易(没有正式的语法AFAIK)。
一旦你完成解析,执行“逐块”通常不起作用。您需要跟踪环境变量更改,当前目录更改等...
话虽如此,您是否看过像jbash这样的内容?
答案 1 :(得分:0)
答案 2 :(得分:0)
这是我到目前为止所得到的。我没有详尽地测试它。
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 = "";
}
}