V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
wanchenyi
V2EX  ›  问与答

shell 脚本求指点

  •  
  •   wanchenyi · 2022-07-09 22:13:56 +08:00 · 1574 次点击
    这是一个创建于 860 天前的主题,其中的信息可能已经有所发展或是发生改变。
    name: "fdfaas...."
    id: "jsdkfksk...."
    ------
    name: "fdfaas...."
    id: "jsdkfksk...."
    -----
    name: "fdfaas...."
    id: "jsdkfksk...."
    
    

    求指点哈,我有一个文本,需要把里面的 name 和 id 对应的值取出来放到一条命令中去执行,每个 name 和 id 是不一样的(只是我为了方便打成一样的),----分隔的是一组,我猜的是可能要用 sed awk ,或者 grep,顺便问了句哪里可以找到提升使用 sed 和 awk 的教程或者资料,

    22 条回复    2022-07-10 21:43:06 +08:00
    ysc3839
        1
    ysc3839  
       2022-07-09 22:18:31 +08:00 via Android
    如果都是这种很规整的,直接按行读取,然后用 grep 之类的提取 key 和 value ,遇到分隔就进行处理,应该没啥问题吧?
    leonhao
        2
    leonhao  
       2022-07-09 22:21:45 +08:00
    哪这么麻烦,bash 脚本逐行遍历就完事了
    wanchenyi
        3
    wanchenyi  
    OP
       2022-07-09 22:25:59 +08:00
    @ysc3839 我想到的就是这种,但我觉得这种要写的还要多一点
    wanchenyi
        4
    wanchenyi  
    OP
       2022-07-09 22:26:47 +08:00
    @leonhao 主要是我简介了这个场景,这个内容已经是我用 grep 过滤出来的
    ysc3839
        5
    ysc3839  
       2022-07-09 22:29:37 +08:00 via Android
    @wanchenyi 个人没觉得多了,用 bash 的话还能直接进行正则匹配,不需要启动新进程了。
    另外建议发原始数据。
    thedrwu
        6
    thedrwu  
       2022-07-09 22:33:03 +08:00 via Android
    sed 可以 N
    TravisMtg
        7
    TravisMtg  
       2022-07-10 09:57:31 +08:00 via iPhone
    这个挺像 yaml 的,用 yq 来提取内容会不会方便点
    ruidoBlanco
        8
    ruidoBlanco  
       2022-07-10 10:07:57 +08:00
    `cat aa.txt|awk -F\" '/^name:/ {name=$2} /^id:/ {id=$2} /^--/ {system("echo "name" "id)}'`
    makelove
        9
    makelove  
       2022-07-10 10:29:50 +08:00
    一般碰到这类复杂格式问题我都直接用调 python 用 heredoc 形式来写,用 bash 真是强人所难了
    wxf666
        10
    wxf666  
       2022-07-10 11:28:12 +08:00
    不懂 awk 如何限制最多分割的列数(比如,按“:”分割,最多两列,最后一列可以包含任意个“:”),只能用正则来匹配了

    假设 name 或 id 的值符合 json 的字符串规范

    awk -v FPAT='(\\w+)|:|"(\\\\?.)*"' 'function output_dict() {if (length(dict)) {printf "%s\0%s\0", dict["name"], dict["id"]; delete dict }} /^\w/{dict[$1]=$3} /^-/{output_dict()} END{output_dict()}' | xargs -0 -n 2 echo


    [输入]
    name: "name1"
    id: "id1"
    ------
    id: "\"id2\": "
    name: ": \"name2\""


    [输出(要由后面的命令去转义了)]
    "name1" "id1"
    ": \"name2\"" "\"id2\": "


    [实际执行]
    echo '"name1"' '"id1"'
    echo '": \"name2\""' '"\"id2\": "'
    wxf666
        11
    wxf666  
       2022-07-10 11:37:45 +08:00
    @ruidoBlanco

    按 " 分割的话,值包含 " 就不好办了( name: "my name is \"xxx\"")

    另外,最后一行不是------的话,最后一组值也没了
    ruidoBlanco
        12
    ruidoBlanco  
       2022-07-10 13:20:57 +08:00
    @wxf666 shell 做这个,quick and dirty 是难以避免的。我那个,用了不到一分钟写出来,我觉得值了。

    如果这么较真说 name 里面可能有引号,我也可以较真说 name 可以有重复。最后一行不是----确实是个 bug ,不过很好改。
    wxf666
        13
    wxf666  
       2022-07-10 14:11:36 +08:00
    @ruidoBlanco 我是 v 站 新人,不太熟悉这儿的风气,不知道回答问题是否该考虑全一点,还是大致给个方向即可

    我觉得,字符串里有 " 是合理且可预见的情况,还是该做处理的,仍属于帖子“提取对应值”主题范畴

    (所以,只是“答得有没有更全面一点”的区别?)

    “name 可以有重复”,这是上一层的工作了吧。另外,楼主也说了“每个 name 和 id 是不一样的”
    ilotuo
        14
    ilotuo  
       2022-07-10 15:30:00 +08:00
    用 python 就简单多了..

    for line in f.readlines():
    if line.startwith("name"):
    name = re.findall(r".*\"(.+?)\"",line)[0]
    else if line.startwith("id"):
    id = re.findall(r".*\"(.+?)\"",line)[0]
    else if line.startwith("---"):
    os.system('xxxxx')
    wanchenyi
        15
    wanchenyi  
    OP
       2022-07-10 21:04:50 +08:00
    @wxf666
    @ruidoBlanco name 没有引号,应该是 uuid 之类的,
    wanchenyi
        16
    wanchenyi  
    OP
       2022-07-10 21:05:34 +08:00
    @ilotuo 感谢你哦,我也是写 Python ,笑哭,这里有一些场景,限制 ,还是得上 shell ,
    wanchenyi
        17
    wanchenyi  
    OP
       2022-07-10 21:06:38 +08:00
    @ysc3839 那么多数据记不住,哈哈
    wanchenyi
        18
    wanchenyi  
    OP
       2022-07-10 21:06:56 +08:00
    @TravisMtg 我去了解哈
    wanchenyi
        19
    wanchenyi  
    OP
       2022-07-10 21:07:29 +08:00
    @ruidoBlanco 感谢
    wanchenyi
        20
    wanchenyi  
    OP
       2022-07-10 21:08:51 +08:00
    感谢各位的围观,8 楼的老哥的答应是我想要的答案。
    ysc3839
        21
    ysc3839  
       2022-07-10 21:18:58 +08:00 via Android
    @wanchenyi 最好还是能提供一下原始数据,避免遇到一些特殊情况。
    另外个人还是觉得按行处理并使用 bash 内置的正则匹配是较好的选择。
    wxf666
        22
    wxf666  
       2022-07-10 21:43:06 +08:00
    @wanchenyi 8 楼的应该还不是完整的答案,除非:

    1. 不要最后一组数据了
    2. 保证 name 和 id 里的值不会出现一些如 $ ` 的特殊字符,否则会出现任意执行代码漏洞

    如 id: "恶意代码:$(sleep 300)" 可以让你的 shell 卡五分钟
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2878 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 07:04 · PVG 15:04 · LAX 23:04 · JFK 02:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.