【问题标题】:Swapping Two Strings using Sed使用 Sed 交换两个字符串
【发布时间】:2018-01-19 15:21:27
【问题描述】:

我有一个文件,我在其中尝试更改两个字符串或尝试相互交换..

cat filename| grep m07

filesystem special="/abc/ca97" raw="/abc/ca97" directory="/mount/m07" 
filesystem special="/abc/d1107" raw="/abc/d1107" directory="/m07"

所以我尝试将 /mount/m07 与 /m07 交换,以便所需的输出应该在操作之后:

filesystem special="/abc/ca97" raw="/abc/ca97" directory="/m07"
文件系统特殊="/abc/d1107" 原始="/abc/d1107" 目录="/mount/m07"

我尝试使用 sed..

sed -e 's/"\/mount\/m07/"\m07/g' -e 's/"\/m07/"\/mount/\/m07' file_name

sed -e 's/"\/m07/"\/mount/\/m07' -e 's/"\/mount\/m07/"\m07/g' file_name

但在这两种情况下,它都替换了两个字符串,所以我在这两行中都得到 /mount/m07 或 /m07...

您能否建议达到所需输出的路径...

【问题讨论】:

    标签: linux shell unix awk sed


    【解决方案1】:

    简单的sed 将为您完成任务。

    sed '/m07/s#/mount/m07#/m07#;t;/m07/s#/m07#/mount/m07#'    Input_file
    

    对于您提到的 Input_file 或命令的输出,以下将是输出:

    your_command | sed '/m07/s#/mount/m07#/m07#;n;/m07/s#/m07#/mount/m07#' 
    <filesystem special="/abc/ca97" raw="/abc/ca97" directory="/m07" >
    <filesystem special="/abc/d1107" raw="/abc/d1107" directory="/m07">
    

    编辑: 现在也为上述命令添加解释,感谢 Sundeep 让我知道 t 选项比 n 更好。以下代码仅用于解释目的,不用于运行。

    sed '/m07/                    Searching for string m07 in a line, if it is present then only do substitutions in that line.
    s#/mount/m07#/m07#;           Doing substitution here substitute /mount/m07 with m07 here
    t;                            t is for(from man sed page) If  a s/// has done a successful substitution since the last input line was read and since the last t or T command, then branch to label if label is omitted, branch to end of script.
    /m07/s#/m07#/mount/m07#       searching string m07 and then substitute string /m07 with /mount/m07
    '    Input_file               Mentioning Input_file.
    

    【讨论】:

    • @User123, 在sed 我们也可以创建自己的分隔符,例如--> sed '/m07/s@/mount/m07@/m07@' Input_file
    • 看起来每个人都错过了这个问题 - 它说交换...所以 /mount/m07 更改为 /m07/m07 更改为 /mount/m07
    • 好吧,我尝试了你提到的命令,但它在两行中都显示 /m07,而我试图交换它们以获得这个输出.. filesystem special="/abc/ca97" raw=" /abc/ca97" directory="/m07" filesystem special="/abc/d1107" raw="/abc/d1107" directory="/mount/m07"
    • @RavinderSingh13 using n 将适用于给定的示例,但不是通用解决方案..只需在给定示例之间添加一条线,您就会看到
    • @RavinderSingh13:感谢 Ravinder 的解释.. :)
    【解决方案2】:

    问题被标记为linux,所以我假设GNU sed 可用(不确定以下解决方案是否为POSIX)。还假设两个字符串都不存在于同一行中

    $ sed 's#/mount/m07#/m07#; t; s#/m07#/mount/m07#' ip.txt
    filesystem special="/abc/ca97" raw="/abc/ca97" directory="/m07" 
    filesystem special="/abc/d1107" raw="/abc/d1107" directory="/mount/m07"
    
    • t 命令将在成功替换时跳转到指定标签
    • 没有标签,t 将跳过其余命令并开始下一个循环
    • 所以,如果s#/mount/m07#/m07# 成功,t 命令将告诉sed 跳过其余命令并读取下一行进行处理
    • 但如果第一次替换不成功,则会尝试第二次替换

    对于非 GNU 版本 - 感谢 @anubhava

    sed -e 's#/mount/m07#/m07#;t' -e 's#/m07#/mount/m07#'
    #or
    sed -e 's#/mount/m07#/m07#' -e 't' -e 's#/m07#/mount/m07#'
    

    进一步阅读

    【讨论】:

    • ++ 等价 POSIX sed woule be: sed -e 's#/mount/m07#/m07#;t' -e 's#/m07#/mount/m07#' file
    • @anubhava 为什么第一个st 可以在一起,而第二个s 需要分开?
    • 因为 POSIX sed 尝试查找 label 之后出现在 t 之后的任何内容。即使在t 之后的; 也会导致POSIX sed 失败。
    • @anubhava Sundeep:我明白了!谢谢:)
    【解决方案3】:
    $ cat sedswap.txt 
    /mount/m07
    /m07
    
    $ sed -e 's/\/mount\/m07/\/rm07/g' -e 's/\/m07/\/mount\/m07/g' -e 's/\/rm07/\/m07/g' sedswap.txt
    /m07
    /mount/m07
    

    基本上使用临时变量方法

    【讨论】:

    • 或者像其他人之前提到的在 sed $ sed -e 's#/mount/m07#/rm07#g' -e 's#/m07#/mount/m07#g' -e 's#/rm07#/m07#g' sedswap.txt 中使用自定义分隔符
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多