有时候,我们调用Shell命令来完成一些操作会方便点。比如复制文件调用cp 'src' 'dest'
命令。但是如果源路径或者目标路径中包含一些Linux Shell 中的一些特殊字符时,可能命令执行的结果并不是我们想要的。此时我们就需要对这些命令进行转义。
# 复制文件
cp 'src' 'dest'
# 移动文件
mv 'src' 'dest'
# 创建文件
touch 'fileName'
# 创建文件夹
mkdir 'dirName'
*,? [] ,{}
| & ; ( ) < > space tab
|| & && ; ;; ( ) |
'
, "
, \
''
(硬转义)'
(单引号)。""
(软转义)$
用于参数代换 '
用于命令代替\
(转义)之前我不想匹配那么多特殊字符,使用的是单引号的方式来处理路径中的特殊字符,直到有用户反馈操作一直等待。检查半天发现是他的文件名中有单引号'
,导致Shell一直在等待下一个'
输入。所以呢,单引号是不靠谱的,现在是采用第三种方式。
所以:
'
,可以硬转义/**
* 将包含特殊Shell字符的字符串 转换成Shell可执行的字符串
*
* @author yawei
* [email protected]
* @date 18-6-26
* @see Linux Shell 特殊字符
*/
public class ShellCommandConversionUtils {
private static final char[] SPECIAL_CHARS = new char[]{'*', '?', '[', ']', '{', '}', ' ', 0x0D, '=', '>', '<', '|', '&', '(', ')', ';', '!', '\\', '\'', '"'};
public static String convert(String line) {
char[] chars = line.toCharArray();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
for (int j = 0; j < SPECIAL_CHARS.length; j++) {
if (c == SPECIAL_CHARS[j]) {
chars = insert(chars, i);
i++;
}
}
}
return new String(chars);
}
private static char[] insert(char[] chars, int index) {
char[] nChars = new char[chars.length + 1];
System.arraycopy(chars, 0, nChars, 0, index + 1);
nChars[index] = '\\';
System.arraycopy(chars, index, nChars, index + 1, chars.length - index);
return nChars;
}
}
时隔一年,再看这个代码,决定优化一下,测试得出性能提升了5倍。20191108。
1.先查找特殊字符(二分法)
2.在合适的位置插入转义字符
public class ShellCommandConversionUtils {
private static final char[] SPECIAL_CHARS = new char[]{'*', '?', '[', ']', '{', '}', ' ', 0x0D, '=', '>', '<', '|', '&', '(', ')', ';', '!', '\\', '\'', '"'};
static {
Arrays.sort(SPECIAL_CHARS);
}
public static String convert(String line) {
char[] srcChars = line.toCharArray();
int[] specialCharIndexArray = null;
int specialCharCount = 0;
//查找需要转义的字符
for (int i = 0; i < srcChars.length; i++) {
int binarySearch = Arrays.binarySearch(SPECIAL_CHARS, srcChars[i]);
if (binarySearch >= 0) {
if (specialCharIndexArray == null) {
specialCharIndexArray = new int[srcChars.length - i];
}
specialCharIndexArray[specialCharCount++] = i;
}
}
//插入转义字符
if (specialCharCount != 0) {
char[] destChars = new char[srcChars.length + specialCharCount];
int srcIndex = 0;
int cpStart = 0;
for (int i = 0; i < specialCharCount; i++) {
int len = specialCharIndexArray[i] - cpStart;
System.arraycopy(srcChars, srcIndex, destChars, srcIndex + i, len);
destChars[srcIndex + i + len] = '\\';
cpStart = specialCharIndexArray[i];
srcIndex += len;
}
System.arraycopy(srcChars, srcIndex, destChars, srcIndex + specialCharCount, srcChars.length - srcIndex);
return new String(destChars);
} else {
return line;
}
}
}
参考链接:Linux Shell 通配符、元字符、转义符使用实例介绍