移动测试基础 随笔,脚本移植性的问题和解决思路

扫地僧 · 2015年12月26日 · 最后由 hover 回复于 2016年03月28日 · 1943 次阅读

昨天遇到一个问题,某台 Jenkins 服务从 Mac 移植到 Windows,不得不把之前的 shell 脚本用 bat 实现,回想以前也遇到过这种情况

  • 代码中调用脚本;
  • Job 中调用脚本。

文件操作是比较常用的场景,以前用对于的增、删、改、查的实现比较多,在此基础上可以再丰富些功能,那么想法转化成行动吧

需求点

  • 用代码实现 grep,awk,sed 等的部分功能,做成插件,可用于日志的过滤、查询、文件数据的查询、统计等,以替代依赖于平台的脚本,提高移植性;
  • 支持对文件的操作,也支持对已存在于内存的字符串进行操作,分为过滤和查询统计两大功能;
  • 作为一个插件,可扩展性要高。

设计和解决思路

  • 设计过滤、查询统计两个接口,使用泛型(规范和扩展);
  • 文件操作和字符串操作实现这两个接口;

部分实现类代码

/**
 * 设置筛选内容,过滤出包含筛选内容的行
 * @param fname 文件路径
 * @param filter
 * @return 包含筛选内容的所有行
 */
public String grep(String fname, String filter) {
    String find = "";
    String line;
    try {
        inputStream = new FileInputStream(fname);
        encode = EncodingDetect.getJavaEncode(fname);
        sc = new Scanner(inputStream, encode);
        while (sc.hasNextLine()) {
            line = sc.nextLine();
            if (line.contains(filter))
                find = find + line + System.getProperty("line.separator");
        }
    } catch (FileNotFoundException e) {
        find = "";
        e.printStackTrace();
    } finally {
        try {
            if (inputStream != null) {
                inputStream.close();
            }
            if (sc != null) {
                sc.close();
            }
        } catch (IOException e) {
            find = "";
            e.printStackTrace();
        }
    }
    return find.trim();
}

/**
 * 从文件末尾开始,按指定行数输出
 * @param fileName 文件路径
 * @param lines 行数
 * @return 符合条件的行
 */
public String tail(String fileName, int lines) {
    boolean findFirstNonBlankLine = false;
    String line;
    String content = "";
    RandomAccessFile rf = null;

    try {
        rf = new RandomAccessFile(fileName, "r");
        long len = rf.length();
        long start = rf.getFilePointer();
        long nextend = start + len - 1;
        rf.seek(nextend);
        int c = -1;
        while (nextend > start) {
            c = rf.read();
            if (c == '\n' || c == '\r') {
                line = rf.readLine();
                if (lines > 0) {
                    if (null == line || line.trim().isEmpty()) {
                        if (findFirstNonBlankLine) {
                            content = line + System.getProperty("line.separator") + content;
                            lines--;
                        } else {
                            continue;
                        }
                    } else {
                        content = line + System.getProperty("line.separator") + content;
                        findFirstNonBlankLine = true;
                        lines--;
                    }
                }
                nextend--;
            }
            nextend--;
            if (lines == 0)
                break;
            rf.seek(nextend);
            // 当文件指针退至文件开始处,输出第一行
            if (nextend == 0) {
                line = rf.readLine();
                content = line + System.getProperty("line.separator") + content;
                break;
            }
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (rf != null) {
                rf.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return content.trim();
}

/**
 * 文件查询,按指定列指定条件查询
 * @param from 文件路径
 * @param where 查询条件的列标
 * @param condition 查询条件
 * @param column 查询的字段
 * @return 符合条件的查询结果
 */
public List<List<String>> select(String from, int where, String condition, int... column) {
    String line;
    String[] columnOfLine;
    List<String> unitList = null;
    List<List<String>> selectList = new ArrayList<List<String>>();
    try {
        inputStream = new FileInputStream(from);
        encode = EncodingDetect.getJavaEncode(from);
        sc = new Scanner(inputStream, encode);
        while (sc.hasNextLine()) {
            line = sc.nextLine();
            line = line.trim().replaceAll(" +", " ").replaceAll("\t+", " ");
            if (line.isEmpty()) {
                continue;
            }
            unitList = new ArrayList<String>();
            columnOfLine = line.split(" ");
            if (columnOfLine[where - 1].trim().equals(condition)) {
                if (null != column && column.length > 0) {
                    for (int i = 0; i < column.length; i++) {
                        unitList.add(columnOfLine[column[i] - 1].trim());
                    }
                } else {
                    for (int i = 0; i < columnOfLine.length; i++) {
                        unitList.add(columnOfLine[i].trim());
                    }
                }
                selectList.add(unitList);
            }
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        try {
            if (inputStream != null) {
                inputStream.close();
            }
            if (sc != null) {
                sc.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return selectList;
}

作为一个插件,虽然还不够完善,但至少解决了我目前的需求。日常工作中,总会遇到这样那样的问题,如能总结经验教训,转化成有用的东西,何乐而不为,希望对大家有帮助。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 5 条回复 时间 点赞

grep,awk,sed 都有 exe 版,而且不止这些。你可能需要 Cygwin

#1 楼 @mrqyoung 确实可以,条条大道通罗马

#2 楼 @quqing 尽量别往 windows 的技术栈上转. git bash 足够了. 他是 windows 下的 awk grep 和 sed. windows 的 power shell 和 batch 太弱.

用过 perl,各大 linux,unix 系统(aix,hpux,solaris), os x 上 都预装,win 上只需要安装个 active perl 就可以。
脚本都能通用了。

确实不错啊

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册