如何使用sed从字符串中提取多个文本和数字?

时间:2015-01-13 13:06:05

标签: bash shell sed

如何使用'sed'

从一行中提取3个或更多单独的文本

我有以下一行:

echo <MX><[Mike/DOB-029/Post-555/Male]><MX>

到目前为止,我可以通过

提取'DOB-029'
sed -n 's/.*\(DOB-[0-9]*\).*/\1/p'

但我没有收到其他文字,如姓名或帖子。

我的预期输出应为 Mike DOB-029 后555

被修改

假设我在文件中有一个列表,我想从整个列表中提取特定的文本/ ID并将其保存到.txt文件

3 个答案:

答案 0 :(得分:3)

sed 's/.*[\(.*\).\(DOB-[0-9]*\).\(Post-[0-9]*\).*/\1 \2 \3/'应该做到这一点!

\(\)之间的部分是捕获的字符串,可以使用\i并使用i组的索引来调用。

自定义脚本:

#! /bin/bash


fields=${1:-123}
file='/path/to/input'

name=$(sed 's/.*\[\([^\/]*\)\/.*/\1/' $file)
dob=$(sed 's/.*\(DOB-[0-9]*\).*/\1/' $file)
post=$(sed 's/.*\(Post-[0-9]*\).*/\1/' $file)

[[ $fields =~ .*1.* ]] && output=$name
[[ $fields =~ .*2.* ]] && output="$output $dob"
[[ $fields =~ .*3.* ]] && output="$output $post"

echo $output

使用要在file变量中解析的行设置文件(我可以添加更多功能,例如将文件作为参数提供,或者如果您愿意,可以从更大的文件中获取)。并使用int参数执行脚本,如果此int包含'1'它将显示名称,如果为2,它将显示DOB,3将输出post信息。你可以结合到例如'123'或'32'或您喜欢的任何组合。

<强> STDIN

如果要从stdin读取,请使用以下脚本:

#! /usr/bin/env bash

line=$(cat /dev/stdin)

fields=${1:-123}

name=$(echo $line | sed 's/.*\[\([^\/]*\)\/.*/\1/')
dob=$(echo $line | sed 's/.*\(DOB-[0-9]*\).*/\1/')
post=$(echo $line | sed 's/.*\(Post-[0-9]*\).*/\1/')

[[ $fields =~ .*1.* ]] && output=$name
[[ $fields =~ .*2.* ]] && output="$output $dob"
[[ $fields =~ .*3.* ]] && output="$output $post"

echo $output

使用示例:

$ chmod +x script.sh
$ echo '<MX><[Mike/DOB-029/Post-555/Male]><MX>' | ./script.sh 123
Mike DOB-029 Post-555
$ echo '<MX><[Mike/DOB-029/Post-555/Male]><MX>' | ./script.sh 12
Mike DOB-029
$ echo '<MX><[Mike/DOB-029/Post-555/Male]><MX>' | ./script.sh 32
DOB-029 Post-555
$ echo '<MX><[Mike/DOB-029/Post-555/Male]><MX>' | ./script.sh 
Mike DOB-029 Post-555

答案 1 :(得分:3)

awk:

的解决方案
echo "<MX><[Mike/DOB-029/Post-555/Male]><MX>" | awk -F[/[] '{print $2, $3, $4}'

我们将分隔符设置为/[-F[/[])。然后我们只打印$2, $3 and $4字段2nd, 3rd and 4th fields

使用 sed:

echo "<MX><[Mike/DOB-029/Post-555/Male]><MX>" | sed 's/\(^.*\[\)\(.*\)\(\/[^/]*$\)/\2/; s/\// /g'

答案 2 :(得分:1)

使用bash替换内置。

line="<MX><[Mike/D0B-029/Post-555/Male]><MX>"; 
linel=${line/*[/}; liner=${linel%\/*}; echo ${liner//\// }