所以我有一个像这样的字符串LST = fr, de, pl, ru, ch, us, uk, ca
。在这里,我必须为将来的 grep 操作创建一个正则表达式模式,因此我必须修改我的字符串以像这样匹配fr\|de\|pl\|ru\|ch\|us\|uk\|ca
set LST = `grep "^LST *=" /remote/file/config.ini | sed 's/LST *= *//' | sed 's/ *//g' | tr , "\|"`
不幸的是,tr , "\\|"
不会替换给定的字符来创建我的正则表达式模式...结果是frdeplruchusukca
。如何创建正则表达式模式,或者如何(例如)找到 LST 变量的出现de
并将找到的值设置为我的 LST 变量?
配置.ini 示例
; sample of ini file
[SITE_PREF]
LST = fr, de, pl, ru, ch, us, uk, ca
TASKLIST = T1,TT3,TT0
答案1
好的,首先,tr
一次只能处理一个字符,它不能,
用 a 替换 a \|
(一到两个字符)。因此,请使用sed
:sed -e 's/,/\\|/'
第二,你可以将 thegrep
和sed
s 结合起来,这似乎适用于 Bash 和 GNU sed:
$ LST=$(sed -n '/^LST *=/ {s/^LST *= *//; s/, */\\|/g; p}' config.ini)
$ echo "$LST"
fr\|de\|pl\|ru\|ch\|us\|uk\|ca
(这基本上是说:在所有匹配的行上/^LST *=/
,执行大括号中的操作:两个s
替换并p
打印该行。)
三,对于您的tr
,您应该将逗号更改为反斜杠或管道,具体取决于引用是否有效,即
$ echo "fr,de,pl" | tr , "\|"
fr|de|pl
$ echo "fr,de,pl" | tr , '\\|'
fr\de\pl
但你没有,反而一无所获。我无法用 Bash 重现这一点,但该set
语法看起来像csh
,并且我使用 时得到了一些奇怪的行为tcsh
。在某些情况下。不是全部。
好的:
$ tcsh
> echo "fr,de,pl" | sed 's/,/\\|/'
fr\|de,pl
> set LST = `echo "fr,de,pl" | sed 's/,/\\|/'`
> printf "%s\n" "$LST"
fr\|de,pl
不太好:
$ tcsh
> echo "fr,de,pl" | sed 's/, */\\|/'
fr\|de,pl
> set LST = `echo "fr,de,pl" | sed 's/, */\\|/'`
> printf "%s\n" "$LST"
fr|de,pl
我能看到的唯一区别是第二种情况下的星号。
答案2
和awk
:
... | awk -F'= ' '{gsub(", ", "\\|", $2); print $2}'
-F '= '
将字段分隔符设置为=
gsub(", ", "\\|", $2)
将第二个字段中的,
全部替换为\|
print $2
打印第二个字段
例子:
$ awk -F'= ' '{gsub(", ", "\\|", $2); print $2}' <<<'LST = fr, de, pl, ru, ch, us, uk, ca'
fr\|de\|pl\|ru\|ch\|us\|uk\|ca
答案3
fr\|de\|pl\|ru\|ch\|us\|uk\|ca
然而,作为 grep 的正则表达式,它不是标准/可移植的:
fr
de
pl
ru
ch
us
uk
ca
这是用换行符分隔的项目,是标准的,也可以用于grep -F
固定字符串搜索(因此,如果您的搜索项包含正则表达式运算符,则不会出现问题)。
所以你可以这样做(这里使用 POSIX shell 语法,你不想用于csh
脚本编写):
search_term=$(
sed '
/^LST *= */!d
s///
s/ *, */\
/g' config.ini
)
grep -F -- "$search_term" some-file
如果您的grep
实现支持它,您还可以传递-w
仅搜索整个单词的选项。
答案4
perl -p0E '($_)= /LST = (.*)/; s/, /\\|/g' config.ini