【问题标题】:How to extract multiple text and numbers from a string using sed? [duplicate]如何使用 sed 从字符串中提取多个文本和数字? [复制]
【发布时间】:2015-03-11 10:54:09
【问题描述】:

如何使用 'sed' 从一行中提取 3 个或更多单独的文本

我有以下行:

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

到目前为止,我可以通过这样做来提取“DOB-029”

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

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

我的预期输出应该是 Mike DOB-029 Post-555

编辑

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

【问题讨论】:

  • 你的预期输出是什么?
  • 我的预期输出应该是 Mike DOB-029 Post-555
  • 那么最后一个区块/Male呢?问题背后的逻辑是什么?提取所有/ 分离的东西?
  • 我什么都不想要。目的是仅显示由 '/' 分隔的前 3 个文本

标签: bash shell sed


【解决方案1】:

sed 's/.*[\(.*\).\(DOB-[0-9]*\).\(Post-[0-9]*\).*/\1 \2 \3/' 应该可以解决问题!

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

自定义使用脚本:

#! /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' 或任何你喜欢的组合。

标准输入

如果您想从标准输入读取,请使用以下脚本:

#! /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

【讨论】:

  • 有没有办法修改此代码或创建脚本,以便我可以选择在不同时间获取文本?因此,如果我只想取名字或 DOB-029 或 Post-555 或两者兼而有之
  • 谢谢。这帮助很大
  • 很高兴,您可以通过接受答案来感谢我:)
【解决方案2】:

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'

【讨论】:

  • 我最近恋爱了.. :-)
  • 如果 OP 没有要求 sed,我也会建议 awk。具有编程语言功能的脚本语言,没有办法击败它:)
  • 这是个好主意,但它可能不适用于我可能拥有的所有字段,如果多个文件之间的字段不一致怎么办?所以 DOB-029 可能不会一直在第二场
  • @Mikey:请根据不同的场景修改您的问题...
  • @Mikey: 或者给出一个不起作用的场景。我们可以解决这个问题。
【解决方案3】:

使用 bash 替换内置函数。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-18
    • 2017-01-31
    • 2014-08-21
    • 2012-07-01
    • 1970-01-01
    • 2012-11-03
    • 1970-01-01
    相关资源
    最近更新 更多