String bash:查找字符串中的不规则值

String bash:查找字符串中的不规则值,string,bash,String,Bash,我正在寻找字符串中匹配后的值。 假设我有两个字符串: string1="Name: John Doe Age: 28 City: Oklahoma City" string2="Name: Jane Age: 29 Years City: Boston" 现在我想设置三个参数:姓名、年龄和城市。 如果我要做: name=$(echo "$string1" | awk '{ print $2 $3 }') city=$(echo "$string1" | awk '{ print $5 }')

我正在寻找字符串中匹配后的值。 假设我有两个字符串:

string1="Name: John Doe Age: 28 City: Oklahoma City"
string2="Name: Jane Age: 29 Years City: Boston"
现在我想设置三个参数:姓名、年龄和城市。 如果我要做:

name=$(echo "$string1" | awk '{ print $2 $3 }')
city=$(echo "$string1" | awk '{ print $5 }')
city=$(echo "$string1" | awk '{ print $8 $9 }
它适用于string1,但显然不适用于string2。 在谷歌搜索之后,我认为我应该把它放到某种数组中,但我真的不知道如何继续

基本上,我希望Name:之后和Age:之前的所有内容都是参数$Name。年龄和城市之间的一切:成为$Age,等等

向Perl解决方案致意(部分摘自我的答案):

捕获名称:

name=`perl -ne 'print $1 if /Name: ([a-zA-Z ]+) Age:/' <<< $string`
name=`perl-ne'打印$1如果/name:([a-zA-Z]+)年龄:/”perl解决方案(部分取自我的答案):

捕获名称:

name=`perl -ne 'print $1 if /Name: ([a-zA-Z ]+) Age:/' <<< $string`

name=`perl-ne'print$1 if/name:([a-zA-Z]+)Age:/”
awk
是最好的解决方案,因为您可以将字段分隔符设置为正则表达式,然后字段是$2、$3和$4

name=$(awk -F'[[:alpha:]]+: ' '{print $2}' <<<"$string1")
 age=$(awk -F'[[:alpha:]]+: ' '{print $3}' <<<"$string1")
city=$(awk -F'[[:alpha:]]+: ' '{print $4}' <<<"$string1")

name=$(awk-F'[[:alpha:]+:'{print$2}'
awk
是最好的解决方案,因为您可以将字段分隔符设置为正则表达式,然后字段是$2、$3和$4

name=$(awk -F'[[:alpha:]]+: ' '{print $2}' <<<"$string1")
 age=$(awk -F'[[:alpha:]]+: ' '{print $3}' <<<"$string1")
city=$(awk -F'[[:alpha:]]+: ' '{print $4}' <<<"$string1")

name=$(awk-F'[[:alpha:]+:''{print$2}'需要bash版本3或更高版本:

if [[ $string1 =~ ^Name:\ (.*)\ Age:\ (.*)\ City:\ (.*) ]] ; then
    name=${BASH_REMATCH[1]}
    age=${BASH_REMATCH[2]}
    city=${BASH_REMATCH[3]}
fi

您可能需要
年龄:\([0-9]*).\City:
如果您不想将“年”包含在
$Years
中,则需要bash版本3或更高版本:

if [[ $string1 =~ ^Name:\ (.*)\ Age:\ (.*)\ City:\ (.*) ]] ; then
    name=${BASH_REMATCH[1]}
    age=${BASH_REMATCH[2]}
    city=${BASH_REMATCH[3]}
fi

您可能需要
年龄:\([0-9]*).\City:
如果您不想在
$Years
中包含“年”,请考虑以下命令:

name=$(awk -F": |Age" '{print $2}' <<< $string1)
age=$(awk -F": |City|Years" '{print $3}' <<< $string1)
city=$(awk -F"City: " '{print $2}' <<< $string1)

name=$(awk-F):|Age“{print$2}”考虑以下命令:

name=$(awk -F": |Age" '{print $2}' <<< $string1)
age=$(awk -F": |City|Years" '{print $3}' <<< $string1)
city=$(awk -F"City: " '{print $2}' <<< $string1)

name=$(awk-F):|Age“{print$2}”类似的东西可能会起作用:

string1="Name: John Doe Age: 28 City: Oklahoma City"
string1ByRow=$(echo "$string1" | perl -pe 's/(\w+:)/\n$1\n/g' | sed '/^$/d' | sed 's/^ *//')
string1Keys=$(echo "$string1ByRow" | grep ':$' | sed 's/:$//')
string1Vals=$(echo "$string1ByRow" | grep -v ':$')

echo "$string1Keys"
Name
Age
City

echo "$string1Vals"
John Doe 
28 
Oklahoma City

类似的方法可能会奏效:

string1="Name: John Doe Age: 28 City: Oklahoma City"
string1ByRow=$(echo "$string1" | perl -pe 's/(\w+:)/\n$1\n/g' | sed '/^$/d' | sed 's/^ *//')
string1Keys=$(echo "$string1ByRow" | grep ':$' | sed 's/:$//')
string1Vals=$(echo "$string1ByRow" | grep -v ':$')

echo "$string1Keys"
Name
Age
City

echo "$string1Vals"
John Doe 
28 
Oklahoma City

您可以使用三个
perl
one行程序为变量赋值-

name=$(perl -pe 's/.*(?<=Name: )([A-Za-z ]+)(?=Age).*/\1/' file)

age=$(perl -pe 's/.*(?<=Age: )([A-Za-z0-9 ]+)(?=City).*/\1/' file)
测试文件:

[jaypal:~/Temp] cat file
string1="Name: John Doe Age: 28 City: Oklahoma City"
string2="Name: Jane Age: 29 Years City: Boston"
[jaypal:~/Temp] perl -pe 's/.*(?<=Name: )([A-Za-z ]+)(?=Age).*/\1/' file
John Doe 
Jane 
[jaypal:~/Temp] perl -pe 's/.*(?<=Age: )([A-Za-z0-9 ]+)(?=City).*/\1/' file
28 
29 Years 
[jaypal:~/Temp] perl -pe 's/.*(?<=City: )([A-Za-z ]+)"/\1/' file
Oklahoma City
Boston
名称:

[jaypal:~/Temp] cat file
string1="Name: John Doe Age: 28 City: Oklahoma City"
string2="Name: Jane Age: 29 Years City: Boston"
[jaypal:~/Temp] perl -pe 's/.*(?<=Name: )([A-Za-z ]+)(?=Age).*/\1/' file
John Doe 
Jane 
[jaypal:~/Temp] perl -pe 's/.*(?<=Age: )([A-Za-z0-9 ]+)(?=City).*/\1/' file
28 
29 Years 
[jaypal:~/Temp] perl -pe 's/.*(?<=City: )([A-Za-z ]+)"/\1/' file
Oklahoma City
Boston
城市:

[jaypal:~/Temp] cat file
string1="Name: John Doe Age: 28 City: Oklahoma City"
string2="Name: Jane Age: 29 Years City: Boston"
[jaypal:~/Temp] perl -pe 's/.*(?<=Name: )([A-Za-z ]+)(?=Age).*/\1/' file
John Doe 
Jane 
[jaypal:~/Temp] perl -pe 's/.*(?<=Age: )([A-Za-z0-9 ]+)(?=City).*/\1/' file
28 
29 Years 
[jaypal:~/Temp] perl -pe 's/.*(?<=City: )([A-Za-z ]+)"/\1/' file
Oklahoma City
Boston

[jaypal:~/Temp]perl-pe的/*(?您可以使用三个
perl
一行程序为变量赋值-

name=$(perl -pe 's/.*(?<=Name: )([A-Za-z ]+)(?=Age).*/\1/' file)

age=$(perl -pe 's/.*(?<=Age: )([A-Za-z0-9 ]+)(?=City).*/\1/' file)
测试文件:

[jaypal:~/Temp] cat file
string1="Name: John Doe Age: 28 City: Oklahoma City"
string2="Name: Jane Age: 29 Years City: Boston"
[jaypal:~/Temp] perl -pe 's/.*(?<=Name: )([A-Za-z ]+)(?=Age).*/\1/' file
John Doe 
Jane 
[jaypal:~/Temp] perl -pe 's/.*(?<=Age: )([A-Za-z0-9 ]+)(?=City).*/\1/' file
28 
29 Years 
[jaypal:~/Temp] perl -pe 's/.*(?<=City: )([A-Za-z ]+)"/\1/' file
Oklahoma City
Boston
名称:

[jaypal:~/Temp] cat file
string1="Name: John Doe Age: 28 City: Oklahoma City"
string2="Name: Jane Age: 29 Years City: Boston"
[jaypal:~/Temp] perl -pe 's/.*(?<=Name: )([A-Za-z ]+)(?=Age).*/\1/' file
John Doe 
Jane 
[jaypal:~/Temp] perl -pe 's/.*(?<=Age: )([A-Za-z0-9 ]+)(?=City).*/\1/' file
28 
29 Years 
[jaypal:~/Temp] perl -pe 's/.*(?<=City: )([A-Za-z ]+)"/\1/' file
Oklahoma City
Boston
城市:

[jaypal:~/Temp] cat file
string1="Name: John Doe Age: 28 City: Oklahoma City"
string2="Name: Jane Age: 29 Years City: Boston"
[jaypal:~/Temp] perl -pe 's/.*(?<=Name: )([A-Za-z ]+)(?=Age).*/\1/' file
John Doe 
Jane 
[jaypal:~/Temp] perl -pe 's/.*(?<=Age: )([A-Za-z0-9 ]+)(?=City).*/\1/' file
28 
29 Years 
[jaypal:~/Temp] perl -pe 's/.*(?<=City: )([A-Za-z ]+)"/\1/' file
Oklahoma City
Boston

[jaypal:~/Temp]perl-pe的/*(?我提出了一个通用解决方案:

keys=() values=()
for word in $string; do
    wlen=${#word}
    if [[ ${word:wlen-1:wlen} = : ]]; then
        keys+=("${word:0:wlen-1}") values+=("")
    else
        alen=${#values[@]}
        values[alen-1]=${values[alen-1]:+${values[alen-1]} }$word
    fi
done

我提出一个通用解决方案:

keys=() values=()
for word in $string; do
    wlen=${#word}
    if [[ ${word:wlen-1:wlen} = : ]]; then
        keys+=("${word:0:wlen-1}") values+=("")
    else
        alen=${#values[@]}
        values[alen-1]=${values[alen-1]:+${values[alen-1]} }$word
    fi
done

bash-3.2$cat sample.log

string1="Name: John Doe Age: 28 City: Oklahoma City"
string2="Name: Jane Age: 29 Years City: Boston"
使用awk匹配内置函数:

awk ' { match($0,/Name:([A-Za-z ]*)Age:/,a); match($0,/Age:([ 0-9]*)/,b);  match($0,/City:([A-Za-z ]*)/,c); print a[1]":" b[1]":"c[1] } ' sample.log
输出:

 John Doe : 28 : Oklahoma City
 Jane : 29 : Boston

bash-3.2$cat sample.log

string1="Name: John Doe Age: 28 City: Oklahoma City"
string2="Name: Jane Age: 29 Years City: Boston"
使用awk匹配内置函数:

awk ' { match($0,/Name:([A-Za-z ]*)Age:/,a); match($0,/Age:([ 0-9]*)/,b);  match($0,/City:([A-Za-z ]*)/,c); print a[1]":" b[1]":"c[1] } ' sample.log
输出:

 John Doe : 28 : Oklahoma City
 Jane : 29 : Boston


很好,但它将返回
age=“29年”
而不是
age=“29”
@anubhava根据OP,这是正确的行为。“年龄:和城市之间的一切:成为$age”@SiegeX:谢谢你的建议。我真的很感激。很好,但它将返回
age=“29年”
而不是
age=“29年”
@anubhava根据OP,这是正确的行为。“年龄:和城市之间的一切:成为$Age”@SiegeX:谢谢你的建议。我真的很感激。很好,但它将返回Age=“29年”而不是Age=“29年”@choroba您应该恢复更改,根据OP,这是预期的行为。@choroba:Awesome。正如我预期的那样工作。谢谢!很好,但它将返回age=“29岁”,而不是age=“29岁”@choroba您应该恢复更改,这是OP预期的行为。@choroba:Awesome。正如我预期的那样工作。谢谢!同样的问题,它也会返回age=“29岁”,而不是age=“29”看到其他评论,我也认为OP是正确的。谢谢@EduardoIvanec的帮助。同样的问题,它也会返回age=“29岁”而不是age=“29”。看到其他评论,我也认为OP是正确的。谢谢@EduardoIvanec的帮助。这将返回age=“29岁”而不是age=“29岁”;p这是故意的,有一例年龄为29岁,另一例年龄为28岁在另一种情况下没有太多的意义。你不能对
$age
变量进行任何比较。这可能是故意的,但根据给定的规范,它是不正确的。他没有说他想对$age进行数字比较。然而,他确实说出了年龄:和城市:to be$age之间的所有内容。我将把它留给OP来选择选择最佳行为(&choose the best behavior)。如果我对其进行编码,我将永远不会在我的
$age
变量中获取
“years”
。如果我需要打印
“29 years”
我稍后会自己添加。@anubhava:谢谢你的努力。我很感激。我实际上打算保留这一切,但再次感谢你的努力。这将返回age=“29”而不是age=“29岁”;p有一次是故意的,age=“29岁”,age=“28”在另一种情况下没有太多的意义。你不能对
$age
变量进行任何比较。这可能是故意的,但根据给定的规范,它是不正确的。他没有说他想对$age进行数字比较。然而,他确实说出了年龄:和城市:to be$age之间的所有内容。我将把它留给OP来选择选择最佳行为(&choose the best behavior)。如果我对其进行编码,我将永远不会在我的
$age
变量中获取
“years”
。如果我需要打印
“29 years”
我稍后会自己附加它。@anubhava:谢谢你的努力。我很感激。我实际上打算保留这一切,但再一次。谢谢你的努力。谢谢你的建议。谢谢你的建议。请不要签署你的帖子。请参阅请不要签署你的帖子。请参阅你也可以使用awk内置FS参数并执行此操作方法也是一样。
bash-3.2$awk'BEGIN{FS=“Name:| Age:| Years | Years.*City:| City:;}{if(NF>=4){Name=$2;Age=$3;City=$4;print Name:“Age:”City;}}}sample.log
输出`John Doe:28:俄克拉荷马城“Jane:29:波士顿”`您也可以使用awk内置的FS参数并以这种方式执行。
bash-3.2$awk'BEGIN FS}=“姓名:|年龄:|年|年。*城市:|城市:;}{if(NF>=4){Name=$2;Age=$3;City=$4;印刷名称:”“Age:”“City;