Shell 使用replace搜索多个字符串以重新生成.config文件

Shell 使用replace搜索多个字符串以重新生成.config文件,shell,awk,sed,Shell,Awk,Sed,我试图从运行在buildroot系统生成的操作系统(即OpenWRT)上的工作系统中重新生成buildroot系统的.config文件。例如,我有一个Seagate GoFLEX Home单元运行在自建的OpenWRT操作系统上,我已经丢失了它的原始.config文件。当然,我可以通过运行makemenuconfig并开始选择所有包来重新生成.config文件。但是,这个过程非常乏味。因此,我提出了以下过程来重新生成.config文件 登录我的Seagate GoFLEX Home unit并执

我试图从运行在buildroot系统生成的操作系统(即OpenWRT)上的工作系统中重新生成buildroot系统的.config文件。例如,我有一个Seagate GoFLEX Home单元运行在自建的OpenWRT操作系统上,我已经丢失了它的原始.config文件。当然,我可以通过运行makemenuconfig并开始选择所有包来重新生成.config文件。但是,这个过程非常乏味。因此,我提出了以下过程来重新生成.config文件

  • 登录我的Seagate GoFLEX Home unit并执行opkg list installed | awk'{print$1}'>/tmp/opkg-list-installed.txt生成已安装软件包列表,以显示已安装的软件包

    在awk处理之前,opkg list installed dump的摘录如下所示:

    ac-power-control-by-USB-hub - 0.0.1-1
    ahcpd - 0.53-2
    alsa-lib - 1.0.28-1
    alsa-lib-dev - 1.0.28-1
    ...
    
    ac-power-control-by-USB-hub
    ahcpd
    alsa-lib
    alsa-lib-dev
    ...
    
    # CONFIG_PACKAGE_ac-power-control-by-USB-hub is not set
    # CONFIG_PACKAGE_ahcpd is not set
    # CONFIG_PACKAGE_alsa-lib is not set
    # CONFIG_PACKAGE_alsa-lib-dev is not set
    # CONFIG_PACKAGE_amrnb is not set
    ...
    
    经过awk处理后,如下所示:

    ac-power-control-by-USB-hub - 0.0.1-1
    ahcpd - 0.53-2
    alsa-lib - 1.0.28-1
    alsa-lib-dev - 1.0.28-1
    ...
    
    ac-power-control-by-USB-hub
    ahcpd
    alsa-lib
    alsa-lib-dev
    ...
    
    # CONFIG_PACKAGE_ac-power-control-by-USB-hub is not set
    # CONFIG_PACKAGE_ahcpd is not set
    # CONFIG_PACKAGE_alsa-lib is not set
    # CONFIG_PACKAGE_alsa-lib-dev is not set
    # CONFIG_PACKAGE_amrnb is not set
    ...
    
    .config文件的示例如下所示:

    ac-power-control-by-USB-hub - 0.0.1-1
    ahcpd - 0.53-2
    alsa-lib - 1.0.28-1
    alsa-lib-dev - 1.0.28-1
    ...
    
    ac-power-control-by-USB-hub
    ahcpd
    alsa-lib
    alsa-lib-dev
    ...
    
    # CONFIG_PACKAGE_ac-power-control-by-USB-hub is not set
    # CONFIG_PACKAGE_ahcpd is not set
    # CONFIG_PACKAGE_alsa-lib is not set
    # CONFIG_PACKAGE_alsa-lib-dev is not set
    # CONFIG_PACKAGE_amrnb is not set
    ...
    
  • 将/tmp/opkg-list-installed.txt传输到构建根系统所在的主机

  • 使用sed处理生成的列表文件(/tmp/opkg list installed.txt),以刷新.config文件,如下所示

    #!/bin/sh
    
    LIST="/tmp/opkg-list-installed.txt"
    FCFG="/tmp/.config"
    
    echo -n "Processing "
    
    for f in $(cat $LIST)
    do
        echo -n "."
        sed -i "s|# CONFIG_PACKAGE_$f is not set|CONFIG_PACKAGE_$f=y|g" $FCFG
    done
    
    echo
    echo "done"
    
  • 由于某些包包含子包和/或子模块,因此在运行make menuconfig以重新刷新(重新生成).config文件之前,此过程不会完成

    以下是我希望上述摘录.config文件的外观:

    CONFIG_PACKAGE_ac-power-control-by-USB-hub=y
    CONFIG_PACKAGE_ahcpd=y
    CONFIG_PACKAGE_alsa-lib=y
    CONFIG_PACKAGE_alsa-lib-dev=y
    # CONFIG_PACKAGE_amrnb is not set
    ...
    
  • 在上面的步骤#3中,我的AMD64计算机大约需要100秒才能重新生成.config文件。对我来说,这个过程有点慢,我想知道这里是否有人知道从已安装软件包列表中重新生成.config文件的更好方法


    EDIT:我用一些示例数据更新了上述内容。

    使用
    for
    循环和
    cat
    是shell中的反模式。您应该在读取循环时使用
    。但是,代码运行缓慢的主要原因似乎是您正在调用
    sed
    ,并对
    $LIST
    的每个单词运行一次整个文件
    $FCFG
    。我建议采用完全不同的方法,使用
    awk
    而不是循环:

    awk 'NR==FNR{a[$0];next}{for(i in a)sub("# CONFIG_PACKAGE_" i " is not set", "CONFIG_PACKAGE_" i "=y")}1' "$LIST" "$FCFG"
    
    第一个块将
    $LIST
    读入内存,第二个块执行与使用
    sed
    执行的替换相同的替换

    我假设您的文件
    $LIST
    每行包含一个单词

    要“就地”执行编辑,可以使用

    awk '...' "$LIST" "$FCFG" > tmp && mv tmp "$FCFG"
    
    只需稍加修改(将第一块中的
    $0
    更改为
    $1
    ),即可跳过一步,从原始输入文件转到所需输出:

    $ cat list
    ac-power-control-by-USB-hub - 0.0.1-1
    ahcpd - 0.53-2
    alsa-lib - 1.0.28-1
    alsa-lib-dev - 1.0.28-1
    $ cat config
    # CONFIG_PACKAGE_ac-power-control-by-USB-hub is not set
    # CONFIG_PACKAGE_ahcpd is not set
    # CONFIG_PACKAGE_alsa-lib is not set
    # CONFIG_PACKAGE_alsa-lib-dev is not set
    # CONFIG_PACKAGE_amrnb is not set
    $ awk 'NR==FNR{a[$1];next}{for(i in a)sub("# CONFIG_PACKAGE_" i " is not set", "CONFIG_PACKAGE_" i "=y")}1' list config
    CONFIG_PACKAGE_ac-power-control-by-USB-hub=y
    CONFIG_PACKAGE_ahcpd=y
    CONFIG_PACKAGE_alsa-lib=y
    CONFIG_PACKAGE_alsa-lib-dev=y
    # CONFIG_PACKAGE_amrnb is not set
    
    Sed在一个可以是多行的“程序”上工作。 将编辑内容汇编到文件中:

    for f in $(</tmp/opkg-list-installed.txt)
    do echo "s@# ... $f@...$f=y@g" ; done > /tmp/edits
    sed -i -f /tmp/edits $FCFG
    
    以美元为单位的f的
    (/tmp/edits)
    sed-i-f/tmp/edits$FCFG
    
    $LIST
    看起来像什么?你能发布一个示例吗?很抱歉丢失了数据。我已经编辑了原始帖子以包含一些示例数据。我对awk不太熟悉,但它似乎不起作用。我真的不知道会发生什么,但脚本似乎从未触及opkg-LIST-installed.txt和.config文件(两个文件的时间戳和大小都保持不变)。我甚至试图用$I替换I,但不幸的是,结果是相同的问题。缺少一个
    {print}
    块,这意味着不会打印任何内容。我在一行的末尾添加了一个
    1
    ,这是
    {print}的常用缩写
    。它现在应该打印到标准输出,然后如果您对输出满意,可以使用第二个代码块中的重定向来覆盖原始文件。@user3767809我添加了一个演示,演示如何从原始列表转到所需的输出。这很管用。如果您从我的原始帖子中注意到,我使用已安装的opkg列表| awk'{print$1}“>/tmp/opkg-list-installed.txt生成列表。由于我对awk不太熟悉,您认为您可以帮助我将其与您的单行awk组合成一个单行代码吗?@user3767809上一个示例就是这样做的,因为它使用
    $1
    保存数组
    a
    中的第一个字段。