使用 bash,我运行以下命令:declare -p | grep 'declare -- '
这将打印整行。我想打印相同的行,但我想排除匹配本身。即,我可以将其... | grep pattern | sed 's/pattern//'
作为单个命令执行吗?这就像选项的反面-o
。
我的命令输出如下:
...
declare -- MAX_CONNECTIONS_PER_SERVER="6"
declare -- OPTERR="1"
declare -- OSTYPE="linux-gnu"
...
但我想输出这个:
...
MAX_CONNECTIONS_PER_SERVER="6"
OPTERR="1"
OSTYPE="linux-gnu"
...
通常,我只会将其通过管道传递给sed
,但巧合的是,我今天想这样做两次。我查看了手册页,但没有看到任何可以执行此操作的选项。
仅返回匹配模式之后的行部分是一个非常相似的问题。也许它甚至是重复的。有人可能会说我的有点窄:它保证我正在 grep 的模式和我正在删除的模式将是相同的。我想删除x
.问题想删除.*x
。
答案1
那应该只是:
declare -p | sed -n 's/^declare -- //p'
但这种解析输出的方法declare -p
是有缺陷的。
VAR=$'\ndeclare -- reboot #'
例如,如果环境中有一个,并且您将该输出提供给 shell 进行解释怎么办?
另请注意,对于已声明但未分配任何值的变量,bash
会打印:declare -- VARNAME
,因此在 之后declare reboot
,上面的代码也会输出reboot
。
你可以将其更改为:
declare -p | LC_ALL=C sed -n 's/^declare -- \(.*=\)/\1/p'
限制分配的变量,但这仍然不能解决包含换行符的变量的问题(即使仅对于变量来说,这也是常见的$TERMCAP
)。
相反,你可以使用这种黑客:
(
export LC_ALL=C
eval '
declare()
if [[ $1 = -- ]]; then
printf "%s=%q\n" "${2%%=*}" "${2#*=}"
fi'"
$(declare -p | sed 's/[][()]/\\&/g')"
)
declare -p
在重新定义为一个函数(如果第一个参数是 则打印第二个参数)之后,我们评估在数组和关联数组表示中使用的转义(
、)
和[
的输出。使用风险自负,过去 bash 的输出被认为是不安全的,添加转义也可能会增加复杂性,特别是对于接受的行长度有限制的实现。]
declare
--
declare -p
sed
sed
在 中zsh
,你可以这样做:
typeset ${(k)parameters[(R)scalar]}
打印变量的定义标量并且没有任何属性(甚至没有特别的也不捆绑)这似乎是你的意图。
typesetsilent
但请注意,如果在函数内调用(在这种情况下它将把所有这些变量声明为本地变量)或者启用该选项,则它不起作用。
另一种可以解决这个问题并让您更好地控制值的引用方式的方法是:
() for 1 do print -r -- $1=${(Pq+)1}; done ${(k)parameters[(R)scalar]}
q+
给出与 所使用的类似的引用样式typeset
。用于qq
更安全的引用风格如果您打算在 shell 中使用该输出(可能不是 zsh,或者不是来自同一版本,或者不在同一语言环境或 OS/libc 中)。
答案2
如果可用,请使用grep -P
:
declare -p | grep -Po 'declare -- \K.*'
请注意,您的方法通常不会很好地工作,因为变量可能包含换行符,您将用它来切断grep
并出现语法错误。
参见例如:
declare -- IFS="
"
答案3
您可以使用 Perl 轻松完成:
declare -p | perl -lne'/^declare -- (.*)/ && print $1'
如果你使用确认, 你可以这样做:
declare -p | ack '^declare -- (.*)' --output='$1'
答案4
declare -p |awk -F "--" '/declare --/{print $NF}'
输出
MAX_CONNECTIONS_PER_SERVER="6"
OPTERR="1"
OSTYPE="linux-gnu"