我想出了一些解决办法,但我不喜欢它们。我在想有没有更好的办法。我主要是在寻找一些简洁的,不需要标志的东西,并且在大多数unix系统上都可用。**我也不确定下面哪一个是最便携的。据我所知,唯一不是的是gawk
解决方案。
示例文件
我想解析BAR
变量的值
# a comment
FOO="ENV_FOO"
BAR="ENV_BAR"
textfile="# a comment\nFOO=\"ENV_FOO\"\nBAR=\"ENV_BAR\""
# awk: split on "=" delimiter
echo $textfile | awk -F "=" '/^BAR=/ { gsub(/"/,"",$2); print $2 }'
# awk: replace beginning of string with empty string; handle quotes with tr
echo $textfile | awk '/^BAR=/ { gsub(/^.*BAR=/, ""); print }' | tr -d '"'
# gawk: most straight-forward to me but not portable or DRY
echo $textfile | gawk '/^BAR=/ { print gensub(/^.*BAR="(.*)"$/, "\\1", "g") }'
# grep + sed
echo $textfile | grep ^BAR= | sed -E 's#^.*"(.*)"$#\1#'
# sed only
echo $textfile | sed -nE 's#^BAR="(.*)"$#\1#p'
# perl: maybe I just need to work on remembering these flags as this is succint
echo $textfile | perl -alE 'print $1 if /^BAR="(.*)"$/'
它们中的每一个都以自己的方式简单明了,但许多都需要记住需要包含的特殊标志才能工作。有没有其他标准的unix工具可以处理这个我没有想到的用例?
5条答案
按热度按时间yc0p9oo01#
或
所以不启用 allfeature s with
-E
。-w
启用警告,可能可以将其放在这里。至于“* 记住这些标志 *”的基本原理是非常合理的
-e
告诉解释器将引号之间的内容E赋值为代码;这就是为什么它是一个“一行程序”,一个命令行上的程序。它必须正好在程序前面加上引号-n
打开一个文件,并为所有提交的文件一次提供一行;这是您在处理文件时所需要的。-p
执行相同的操作,* 和 * 打印每一(处理过的)行就这样,对于大多数普通的需求。因此
perl -ne'...' file
在文件的每一行上运行''
中的代码(沿着其他开关的效果);我也总是在-w
中抛出。当然,还有很多其他的开关,在perlrun中有描述,用于更具体的方便或用途。几个突出的
-M
加载一个模块,如-MModuleName
。还可以指定要导入的函数,请参阅文档-0777
一次读取整个文件(“slurp”)。这将设置输入记录分隔符($/
),以便将整个文件视为一个“行”--因此我们仍然需要-n
。-C
后跟Unicode功能的数字/列表,例如-CASD
-l
,用于处理L行结尾,在输入端剥离它们并在输出端追加通常这一行(slurp模式下的文件)会进入
$_
变量,这是Perl中的全面默认值。要查看与Perl为给定的一行程序运行的代码非常接近的代码,请将
-MO=Deparse
添加到开关,它使用B::Deparse编译器后端(通过O模块)tyu7yeag2#
您可以源文件:
6tdlim6h3#
您可以使用
sed
版本的命令,它保证符合POSIX,如下所示-n
和p
标志是标准标志,用于指示sed
仅在正则表达式被Assert为有效时才打印捕获的模式\1
。您还可以在OP中使用在
gawk
变体中定义的正则表达式,如下所示。P.S.请注意,这个问题没有明确的答案,除非您添加更多关于运行此程序的最小系统(可能只需要POSIX)的详细信息。您也可以分析每个建议,并选择最能解决您的用例的建议。
6kkfgxo04#
awk
echo $textfile | awk -F\" '/^BAR=/{print $2}'
您可以使用
"
作为字段分隔符。这样,相关行中的第二个awk值将返回所需的变量值。5m1hhzi45#
这可能有点太可爱了,但是你可以将文本文件转换成一个perl程序,将env赋值转换成散列赋值,并为结果附加一个perl print语句,使用sed:
当你简单地将其导入perl时,它会给你想要的结果:
除了太可爱之外,这当然还有一个额外的负担,那就是对于其他解决方案来说效率有点低--两次而不是一次。
从好的方面来说,sed和perl可能是最****可移植的程序,而且没有任何“标志”,所以……权衡
更新:我突然想到,因为环境变量/语法无论如何都是为shell设计的,同样的想法可以直接用于shell,尽管可能不那么“可移植”,没有任何语法按摩。这是bash:
说明:将
IFS
设置为null将停止“单词拆分”,否则将从文本文件输出中删除换行符。-e
使echo
识别\n
转义序列。通过“命令替换”处理文本文件。-s
到bash
告诉它将标准输入作为脚本。