我正在尝试从文件中读取字符串的子字符串并将其放入变量中。该字符串看起来如下所示:
“dn:uid=myUid,ou=People,dc=mydomain,dc=furtherdomain”
以下操作成功了,但是对我来说太笨重了:
#!/bin/bash
while IFS= read -r line; do
if [[ "$line" == *"uid="* ]]; then
uid1=${line#*uid=}
uid2=${uid1%,*}
uid3=${uid2%,*}
uid=${uid3%,*}
echo "$uid"
fi
done <<< "dn: uid=myUid,ou=People,dc=mydomain,dc=furtherdomain"
7
5 个回答
5
通过bash
使用extglob
(扩展的 glob),您只需一步即可实现此目的:
# enable extended glob
shopt -s extglob
# our input
s="dn: uid=myUid,ou=People,dc=mydomain,dc=furtherdomain"
# cleanup the string using string substitution and declare the variable
declare "${s//+(,*|* )}"
# print the new variable
echo "$uid"
myUid
|
用于%%
匹配最长的后缀,而不是最短的后缀,*
。
$ echo ${uid1}
myUid,ou=People,dc=mydomain,dc=furtherdomain
$ echo ${uid1%,*}
myUid,ou=People,dc=mydomain
$ echo ${uid1%%,*}
myUid
|
$ while IFS= read -r line; do
if [[ $line =~ uid=([^,]+) ]]; then
echo "${BASH_REMATCH[1]}"
fi
done <<< "dn: uid=myUid,ou=People,dc=mydomain,dc=furtherdomain"
myUid
|
解析逗号分隔的行
假设参数以这种形式提交:
dn: uid=myUid,ou=People,dc=mydomain,dc=furtherdomain
甚至
dn: ou=People,uid=myUid,dc=mydomain,dc=furtherdomain
dn: ou=People,dc=furtherdomain,uid=myUid,dc=mydomain
dn: uid=myUid,ou=People,dc=mydomain,dc=furtherdomain,cn=commonname
dn: fn=Full Name,uid=myUid,ou=People,dc=mydomain,dc=furtherdomain
(是的,我呈现她的方式将支持空间!;-)
uid
按要求仅提取一个变量 (
类似于:
#!/bin/bash
IdLine="$*"
while IFS== read -d, name val;do
case $name in
uid ) uid=$val ;;
esac
done < <(printf %s "${IdLine#*: }")
或者,受到uid=
的启发,即使不在第一位也能够找到。
shopt -s extglob
line='dn: fn=Full Name,uid=myUid,ou=People,dc=mydomain,dc=furtherdomain'
uid="${line//+(*uid=|,*)}"
将所有子变量提取到关联数组中。
在下面您可以使用关联数组来索引所有值:
警告:有些字段重复!例如dc
出现了两次!为此,我使用逗号,
将值分隔到同一字段中。
#!/bin/bash
IdLine="$*"
declare -A IdArray='()'
while IFS== read -d, name val;do
if [[ -v IdArray[$name] ]]; then
IdArray[$name]+=",$val"
else
IdArray[$name]="$val"
fi
done < <(printf %s "${IdLine#*: }")
然后
echo ${IdArray[uid]}
你的变量将如下所示:
declare -p IdArray
declare -A IdArray=([dc]="mydomain,furtherdomain" [ou]="People" [uid]="myUid" )
或者
declare -A IdArray=([dc]="mydomain,furtherdomain" [fn]="Full Name" [ou]="People" [uid]="myUid" )
通过函数将所有内容提取到关联数组中。
#!/bin/bash
parseDnLine() {
local -n _aArray=$1
shift
local _idLine="$*" _nam _val
while IFS== read -d, _nam _val; do
if [[ -v _aArray[$_nam] ]]; then
_aArray[$_nam]+=,${_val%$'\n'}
else
_aArray[$_nam]=${_val%$'\n'}
fi
done <<<"${_idLine#*: },"
}
declare -A test{1..4} # Require to declare Associative Array outside of function
parseDnLine test1 dn: ou=People,uid=myUid,dc=mydomain,dc=furtherdomain
declare -p test1
parseDnLine test2 dn: ou=People,dc=furtherdomain,uid=myUid,dc=mydomain
declare -p test2
line='dn: uid=myUid,ou=People,dc=mydomain,dc=furtherdomain,cn=commonname'
parseDnLine test3 "$line"
declare -p test3
line="dn: fn=Full Name,uid=myUid,ou=People,dc=mydomain,dc=furtherdomain"
parseDnLine test4 $line
declare -p test4
会产生类似这样的结果:
declare -A test1=([dc]="mydomain,furtherdomain" [ou]="People" [uid]="myUid" )
declare -A test2=([dc]="furtherdomain,mydomain" [ou]="People" [uid]="myUid" )
declare -A test3=([dc]="mydomain,furtherdomain" [cn]="commonname" [ou]="People" [uid]="myUid" )
declare -A test4=([dc]="mydomain,furtherdomain" [fn]="Full Name" [ou]="People" [uid]="myUid" )
1
-
我刚刚意识到某些字段可能出现多次!我编辑了我的答案并添加了一个函数。
–
|
grep
如果您启用 PCRE ( -P
) 以便能够在uid=
中捕获属性名称 ( ) ,然后匹配属性值并仅输出匹配的子字符串 ( ),则可以通过一次调用执行此操作:-o
grep -oP '(?<=uid=)[a-zA-Z]+' <<< 'dn: uid=myUid,ou=People,dc=mydomain,dc=furtherdomain'
[a-zA-Z]+
如果您的 ID 不仅仅包含字母,您可以用不同的字符集替换。
使用 sed 可以实现相同的效果,无需 PCRE 后视——我们将预期uid
值包装在匹配组中,并将整个字符串替换为仅该\1
匹配组:
sed -E 's/^.*uid=([a-zA-Z]+).*$/\1/' <<< 'dn: uid=myUid,ou=People,dc=mydomain,dc=furtherdomain'
3
-
-P
在 Linux 上很常见;但在其他平台上却不常见。
– -
或者
grep -oP 'uid=\K[^,]+
。你的 sed 将打印不匹配的全部行:sed -nE 's/.*uid=([^,]+).*/\1/p
– -
@tripleee 是的,这就是为什么我建议所有 macOS 用户首先安装所有 GNU 实用程序 😉 以获得所有新功能(bash、coreutils、diffutils、findutils、gnu-sed、grep)
–
|
awk
(您使用的标签之一)与您的问题有何关联–
awk -F '=|,' '{print $2} ' <<< "dn: uid=myUid,ou=People,dc=mydomain,dc=furtherdomain"
–
$2
可能会引用与预期不同的值 ––
–
awk -v FPAT='uid=[^,]+' '{split($1,array,"="); print array[2]}' <<< "dn: uid=myUid,ou=People,dc=mydomain,dc=furtherdomain"
–
|