MANIFEST.MF文件对Import-Package/Export-Package重排列

众所周知,MANIFEST.MF文件中的空格开头的行是相当于拼接在上一行末尾的。很多又长又乱的Import-Package或者Export-Package,有时候想要搜索某个package却可能被换行截断而搜不到。

这时候咱们可以对它进行格式化重新排列,同时又不影响它的正常运行。再排个序方便查找。

排列前 vs 排列后

MANIFEST.MF文件对Import-Package/Export-Package重排列

MANIFEST.MF文件对Import-Package/Export-Package重排列

附上干货 !!!

(脚本方式,对于长一点的package慢的一批,待优化;可对jar文件直接执行,免解压读取META-INF/MANIFEST.MF)

#!/bin/bash

MANIFEST.MF文件对Import-Package/Export-Package重排列
function main() {
    echo $1 | egrep ".jar$|.zip$" &>/dev/null
    if [ $? -eq 0 ];then
        MANIFEST=$(unzip -p $1 META-INF/MANIFEST.MF)
        [ $? -ne 0 ] && echo ${MANIFEST} && exit 1
    else
        MANIFEST=$(cat $1)
    fi
    isWindowsDoc="false"
    # 判断文件格式是windows还是unix
    [ "" != "$(echo "$MANIFEST" | sed -n ":a;N;/\r\n/p;ba")" ] && isWindowsDoc="true"
    MANIFEST=$(echo "$MANIFEST" | dos2unix)

    # 空格开头的行,合并到一行
    MANIFEST=$(echo "$MANIFEST" | sed ":a;N;s/\n //g;ba")

    importPackage=$(echo "${MANIFEST}" | egrep "^Import-Package:" | sed 's/^Import-Package: *//g' | sed 's/ //g')
    exportPackage=$(echo "${MANIFEST}" | egrep "^Export-Package:" | sed 's/^Export-Package: *//g' | sed 's/ //g')

    output=$(echo "${MANIFEST}")
    # 引号外的逗号转为特殊分隔符
    if [ "" != "${importPackage}" ];then
        importPackage=$(dealStrByPython ${importPackage})
        importPackage="Import-Package: \n${importPackage}"
        len=${#importPackage}
        importPackage=$(echo -e "${importPackage:0:$((len-1))}") # 去掉最后一个字符
        oneLineImport=$(echo "${importPackage}" | sed ":a;N;s/\n/#/g;ba") # sed命令不能一行换多行,将换行符转为#号变成一行,替换后#号再转回换行符
        output=$(echo "${output}" | sed 's/^Import-Package:.*/'"${oneLineImport}"'/g' | sed "s/#/\n/g")
    fi
    if [ "" != "${exportPackage}" ];then
        exportPackage=$(dealStrByPython ${exportPackage})
        exportPackage="Export-Package: \n${exportPackage}"
        len=${#exportPackage}
        exportPackage=$(echo -e "${exportPackage:0:$((len-1))}")
        oneLineExport=$(echo "${exportPackage}" | sed ":a;N;s/\n/#/g;ba")
        output=$(echo "${output}" | sed 's/^Export-Package:.*/'"${oneLineExport}"'/g' | sed "s/#/\n/g")
    fi

    if [ "true" == "${isWindowsDoc}" ];then
        echo "${output}" | unix2dos
    else
        echo "${output}"
    fi
}

#按逗号分隔字符串,并忽略双引号中的逗号
#逐个字符遍历
#效率贼慢
function dealStr() {
    str=$1
    newStr=""
    isOpenQuotes="false"
    splitChar="#"
    # 遍历字符串的字符
    for((i=0; i))
    do
        char=${str:$i:1}
        if [ "$char" == '"' ];then
            if [ "$isOpenQuotes" == "false" ];then
                isOpenQuotes="true"
            else
                isOpenQuotes="false"
            fi
        fi
        [ "$char" == "," ] && [ "$isOpenQuotes" == "false" ] && char=${splitChar}
        newStr=${newStr}${char}
    done
    # 按特殊分隔符分割、排序
    echo "${newStr}" | awk -F '#' '{for(n=1;n' | sort
}

#按逗号分隔字符串,并忽略双引号中的逗号
#遍历字符串中的双引号和逗号
#效率快了一点点
function dealStrTest() {
    str=$1
    newStr=""
    isOpenQuotes="false"
    splitChar="#"

    while true
    do
        indexOfQuotes=expr index $str '"'
        indexOfComma=expr index $str ','
        # 处理引号
        if [ $indexOfQuotes -gt 0 ] && [ $indexOfComma -gt 0 ] && [ $indexOfQuotes -lt $indexOfComma ];then
            if [ "$isOpenQuotes" == "false" ];then
                isOpenQuotes="true"
            else
                isOpenQuotes="false"
            fi
            newStr=${newStr}${str:0:$indexOfQuotes}
            str=${str:$indexOfQuotes}
        # 处理逗号
        elif [ $indexOfQuotes -gt 0 ] && [ $indexOfComma -gt 0 ] && [ $indexOfComma -lt $indexOfQuotes ] || [ $indexOfQuotes -eq 0 ] && [ $indexOfComma -gt 0 ];then
            [ "$isOpenQuotes" == "false" ] && newStr=${newStr}${str:0:$indexOfComma-1}${splitChar}
            [ "$isOpenQuotes" != "false" ] && newStr=${newStr}${str:0:$indexOfComma}
            str=${str:$indexOfComma}
        # 逗号没了
        elif [ $indexOfComma -eq 0 ];then
            newStr=${newStr}${str}
            break
        else
            break
        fi
    done
    # 按特殊分隔符分割、排序
    echo "${newStr}" | awk -F '#' '{for(n=1;n' | sort
}

#按逗号分隔字符串,并忽略双引号中的逗号
#使用python逐个字符遍历
#效率更快了
function dealStrByPython() {
    str=$1
    newStr=python -c "
str='$str'
isOpenQuotes=False
splitChar='#'
chArr=[]
for ch in str.replace(' ',''):
    if ch == '\"' :
        isOpenQuotes = bool(1-isOpenQuotes)
    if ch == ',' and isOpenQuotes == False :
        chArr.append(splitChar)
    else :
        chArr.append(ch)
print(''.join(chArr))
"
    # 按特殊分隔符分割、排序
    echo "${newStr}" | awk -F '#' '{for(n=1;n' | sort
}

main $@

(java方式)

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Properties;

public class ManifestFormatter {

    private final static String IMPORT_PACKAGE = "Import-Package";
    private final static String EXPORT_PACKAGE = "Export-Package";
    private final static char SEPARATOR = '#';

    public static void main(String[] args) {
        File mf = new File(args[0]);
        File formatMf = new File(mf.getParentFile(), "MANIFEST.MF.FORMAT");
        if (!mf.exists()) {
            System.out.println(mf.getAbsolutePath() + " is format failed: " + mf.getAbsolutePath() + " is not exits");
            System.exit(2);
        }
        try (BufferedReader br = new BufferedReader(new FileReader(mf)); BufferedWriter bw = new BufferedWriter(new FileWriter(formatMf));) {
            StringBuilder fileToString = new StringBuilder();
            char[] chars = new char[1024];
            int len;
            while ((len = br.read(chars, 0, chars.length)) != -1) {
                fileToString.append(new String(chars, 0, len));
            }

            // 转换MANIFEST.MF文件中的属性为单行模式,并保持原来的文档格式
            String lineSeparator = fileToString.indexOf("\r\n") != -1 ? "\r\n" : "\n";
            String formatStr = fileToString.toString().replaceAll(lineSeparator + " ", "");
            ByteArrayInputStream bi = new ByteArrayInputStream(formatStr.getBytes());
            Properties properties = new Properties();
            properties.load(bi);

            // 回写MANIFEST.MF文件,重新写入Import-Package与Export-Package
            String importPackageStr = properties.getProperty(IMPORT_PACKAGE);
            if (importPackageStr != null && importPackageStr.length() > 0) {
                List importPackageList = getPackageList(importPackageStr);
                String newImportPackageStr = createNewPackage(importPackageList, IMPORT_PACKAGE, lineSeparator);
                formatStr = formatStr.replaceAll("Import-Package:.*" + lineSeparator, newImportPackageStr);
            }
            String exportPackageStr = properties.getProperty(EXPORT_PACKAGE);
            if (exportPackageStr != null && exportPackageStr.length() > 0) {
                List exportPackageList = getPackageList(exportPackageStr);
                String newExportPackageStr = createNewPackage(exportPackageList, EXPORT_PACKAGE, lineSeparator);
                formatStr = formatStr.replaceAll("Export-Package:.*" + lineSeparator, newExportPackageStr);
            }
            bw.write(formatStr);
        } catch (IOException e) {
            System.out.println(mf.getAbsolutePath() + " is format failed: " + e.getMessage());
            e.printStackTrace();
            System.exit(1);
        }
        System.out.println(mf.getAbsolutePath() + " is format successed");
    }

    /**
     * 重新创建Import-Package与Export-Package
     *
     * @param packageList
     * @param packageType
     * @param lineSeparator
     * @return
     */
    private static String createNewPackage(List packageList, String packageType, String lineSeparator) {
        StringBuilder newPackageString = new StringBuilder(packageType).append(":").append(lineSeparator);
        int size = packageList.size();
        for (int i = 0; i < size; i++) {
            newPackageString.append(" ");
            newPackageString.append(packageList.get(i));
            if (i < size - 1) {
                newPackageString.append(",");
            }
            newPackageString.append(lineSeparator);
        }
        return newPackageString.toString();
    }

    /**
     * 单行的Import-Package或Export-Package,转化为list数组
     *
     * @param packageStr  单行的Import-Package或Export-Package
     * @param packageType "Import-Package"或"Export-Package"
     * @return
     */
    private static List getPackageList(String packageStr) {
        boolean isOpenQuotes = false;
        char[] chArr = packageStr.replaceAll(" ", "").toCharArray();
        int len = chArr.length;
        // 双引号外面的逗号,转为分隔符
        for (int i = 0; i < len; i++) {
            if (chArr[i] == '"') {
                isOpenQuotes = !isOpenQuotes;
            }
            if (chArr[i] == ',' && !isOpenQuotes) {
                chArr[i] = SEPARATOR;
            }
        }
        List packageList = Arrays.asList(new String(chArr).split(SEPARATOR + ""));
        Collections.sort(packageList);
        return packageList;
    }

}

Original: https://www.cnblogs.com/zhangzongjian/p/11829599.html
Author: zhangzongjian
Title: MANIFEST.MF文件对Import-Package/Export-Package重排列

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/606842/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球