shell 脚本求指点 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wanchenyi
V2EX    问与答

shell 脚本求指点

  •  
      wanchenyi 2022-07-09 22:13:56 +08:00 1810 次点击
    这是一个创建于 1197 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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     Solana     2555 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 10:16 PVG 18:16 LAX 03:16 JFK 06:16
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86