解释:

解释:

举个例子,供你娱乐:

$ f=/etc/os-release; . $f; cat $f | sed -re 's/(.*)=.*/printf "%20s: %s\\n" "\\$\1" "$\1"/'
printf "%20s: %s\n" "\$NAME" "$NAME"
printf "%20s: %s\n" "\$VERSION" "$VERSION"
printf "%20s: %s\n" "\$ID" "$ID"
printf "%20s: %s\n" "\$ID_LIKE" "$ID_LIKE"
printf "%20s: %s\n" "\$PRETTY_NAME" "$PRETTY_NAME"
printf "%20s: %s\n" "\$VERSION_ID" "$VERSION_ID"
printf "%20s: %s\n" "\$HOME_URL" "$HOME_URL"
printf "%20s: %s\n" "\$SUPPORT_URL" "$SUPPORT_URL"
printf "%20s: %s\n" "\$BUG_REPORT_URL" "$BUG_REPORT_URL"
printf "%20s: %s\n" "\$PRIVACY_POLICY_URL" "$PRIVACY_POLICY_URL"
printf "%20s: %s\n" "\$VERSION_CODENAME" "$VERSION_CODENAME"
printf "%20s: %s\n" "\$UBUNTU_CODENAME" "$UBUNTU_CODENAME"
$ 

...现在真正的问题是:
如何在本地 shell 中执行此操作,而不使用临时文件!?
(因此请避免任何类似操作... >z ; . z ; rm z

xargs 无法做到这一点(IIUC)
源 - 没有这样的选项
bash - 创建一个子shell,因此将看不到变量值。

我尝试过的事情:

$ source <(f=/etc/os-release; . $f; cat $f | sed -re 's/(.*)=.*/printf "%20s: %s\\n" "\\$\1" "$\1"/')
               $NAME: 
            $VERSION: 
                 $ID: 
            $ID_LIKE: 
        $PRETTY_NAME: 
         $VERSION_ID: 
           $HOME_URL: 
        $SUPPORT_URL: 
     $BUG_REPORT_URL: 
 $PRIVACY_POLICY_URL: 
   $VERSION_CODENAME: 
    $UBUNTU_CODENAME: 

$ source < <(f=/etc/os-release; . $f; cat $f | sed -re 's/(.*)=.*/printf "%20s: %s\\n" "\\$\1" "$\1"/')
bash: source: filename argument required
source: usage: source filename [arguments]
 
$ source /dev/fd/0 <(f=/etc/os-release; . $f; cat $f | sed -re 's/(.*)=.*/printf "%20s: %s\n" "\\$\1" "$\1"/')
^C  # no output, CTRL-C
$

预期输出,我再说一遍 - 不使用临时文件/脚本:

               $NAME: Ubuntu
            $VERSION: 20.04.4 LTS (Focal Fossa)
                 $ID: ubuntu
            $ID_LIKE: debian
        $PRETTY_NAME: Ubuntu 20.04.4 LTS
         $VERSION_ID: 20.04
           $HOME_URL: https://www.ubuntu.com/
        $SUPPORT_URL: https://help.ubuntu.com/
     $BUG_REPORT_URL: https://bugs.launchpad.net/ubuntu/
 $PRIVACY_POLICY_URL: https://www.ubuntu.com/legal/terms-and-policies/privacy-policy
   $VERSION_CODENAME: focal
    $UBUNTU_CODENAME: focal

解释:

在我的版本 [上面] 中(下面是 @Scott 的回答的副本),我没有在主 shell 中初始化 /etc/os-release 中的变量,只在子 shell 中初始化。因此,它们无法在主 shell 中打印source <(...)

因此,该单行代码的“修正”版本有效如下:

f=/etc/os-release; source "$f"; source <( sed <"$f" -re 's/(.*)=.*/printf "%20s: %s\\n" "\\$\1" "$\1"/')

其中第一个初始化变量,然后子shell产生要由上面的. source "$f";执行的代码。source <(...)...为了便于阅读,这里用短的.代替了。source

答案1

简短/一般性回答:

你尝试的第一件事是正确的:如果command-list是一个命令列表,运行时输出一个 shell 脚本(即另一个命令列表),你可以使用以下命令执行(动态创建的)脚本

来源 <(命令列表
或者
<(命令列表
事实上,在你的例子中,它工作正常。但它没有给你想要的结果,因为……

详细/具体的答案:

$(…)…和<(…)  (以及 )之类的东西(…) 会创建子 shell。您尝试做的第一件事的问题是,您 . $f在子 shell 中执行了 ,而您执行printf外壳中的命令。因此,解决方案是,您需要执行.在外壳中:

f=/etc/os-release; . "$f"; source <(cat "$f" | sed -re 's/(.*)=.*/printf "%20s: %s\\n" "\\$\1" "$\1"/')

我在两边加了双引号,"$f"因为正确的做法™;只要 的值$f不包含任何奇怪的字符,严格来说,您就不需要它们。当然,您可以将 source上面的 更改为另一个.

f=/etc/os-release; . "$f"; . <(cat "$f" | sed -re 's/(.*)=.*/printf "%20s: %s\\n" "\\$\1" "$\1"/')

我把 UUOC 留给你修复。

相关内容