举个例子,供你娱乐:
$ 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 留给你修复。