【问题标题】:SED command to replace string after occurrence of a characterSED 命令在出现字符后替换字符串
【发布时间】:2021-10-28 05:19:37
【问题描述】:

我正在尝试运行sed 的以下命令:

echo "fOO:paSS,tesT2:fail,TESt:pasS,fdfdhfd:pass,test5:anyresult test,test6:pass asfas " | sed  's/:.*/\L&/;s/\w\+/\u&/g;s/:/ # /g;y/,/\n/' | sed 's/\w\+/&\n/2;P;d'

我得到的输出是:

FOO # Pass
TesT2 # Fail
Test # Pass
Fdfdhfd # Pass
Test5 # Anyresult
Test6 # Pass

期望的输出:

fOO # Pass
tesT2 # Fail
TESt # Pass
fdfdhfd # Pass
test5 # anyresult
test6 # Pass

我想要的是:

  1. Pass”和“fail”应始终使用“P”和“F”大写,无论给出什么输入。
  2. Test”的名称应与 echo 命令中提供的名称保持一致,不应更改。
  3. # 之后和之前应该只有第一个单词。如果用户给出“Test5:Pass successfully”之类的输入,则不应打印successfully

可选要求:

  • 我们能否将其转换为包含 2 列和“n”行的表格?

【问题讨论】:

  • 那么你想要的输出中的第二行是错误的。
  • @triplee 更正了它。谢谢..对此有任何想法吗?
  • (仍然)不明白你是如何从fOOFOO,从tesT2TestT2,从anyresultAnyresult ... ???
  • 我正在使用的 sed 命令将整个单词转换为小写,然后将每个单词的第一个字母转换为大写。但我不希望: 之前提到的字符串转换为小写。

标签: linux shell sed centos


【解决方案1】:
  1. 使用 sedtrcut 来匹配所描述的规范 输出应该是,(而不是不一致的期望输出 OP):

    echo "fOO:paSS,tesT2:fail,TESt:pasS,fdfdhfd:pass,test5:anyresult test,test6:pass asfas " | 
       tr ',' '\n' | 
       sed 's/:[fp]/\U&/;s/:/ # /;s/...$/\L&/' | 
       cut -d ' ' -f '1-3'
    

    输出:

      fOO # Pass
      tesT2 # Fail
      TESt # Pass
      fdfdhfd # Pass
      test5 # anyresult
      test6 # Pass
    
  2. 两列变体输出:

    echo "fOO:paSS,tesT2:fail,TESt:pasS,fdfdhfd:pass,test5:anyresult test,test6:pass asfas " |
       tr ',' '\n' | 
       sed 's/:[fp]/\U&/;s/:/\t/;s/...$/\L&/' | 
       cut -d ' ' -f 1
    

    输出:

    fOO Pass
    tesT2   Fail
    TESt    Pass
    fdfdhfd Pass
    test5   anyresult
    test6   Pass
    

【讨论】:

  • 实际上@agc 结果应该只是“通过”或“失败”。它不应该是“通过”或“通过”或“失败”之类的东西。
  • 我认为最好的方法是将整个字符串保持原样,并将任何出现的任何格式的通过/失败转换为通过或失败。
  • 嗨@agc 实际上我可以使用这样的 awk 命令来实现它:echo "fOO:paSS,tesT2:fail,TESt:pasS,fdfdhfd:pass,test5:anyresulttest,test6:pass asfas" | sed -E 's/:/#/g;s/,/ /g;s/(.\S*)(#)(.)(\S*)\s/\1 \2 \U\3\L\4<br>\n/g;' | awk 'NF < 2 || NF > 3 { $1=""}1' | sed 's/\s//' 你能告诉我如何在通过/失败之前使用# 实现列变体吗?
【解决方案2】:

如果您不介意将sed 命令传送到awk 以进行清理,可以试试这个。

echo "fOO:paSS,tesT2:fail,TESt:pasS,fdfdhfd:pass,test5:anyresult test,test6:pass asfas " | 
sed -E 's/:/#/g;s/,/ /g;s/(.\S*)(#)(.)(\S*)\s/\1  \2 \U\3\L\4\n/g;' | 
awk 'NF < 2 || NF > 3 { $1=""}1' |
sed 's/\s//'

工作原理

s/:/#/g: 更改为 #

s/,/ /g, 更改为空格。

s/(.\S*)(#)(.)(\S*)\s/\1 \2 \U\3\L\4\n/g 这是所有工作发生的地方,首先,我们匹配正则表达式并将其分成组,所以当带回来时,我们可以在此处为组的部分添加大写和小写,并引入新行\n将匹配正则表达式拆分为新行。

awk 'NF &lt; 2 || NF &gt; 3 { $1=""}1' 删除我们不想要的贪婪匹配

输出

fOO # Pass
tesT2 # Fail
TESt # Pass
fdfdhfd # Pass
test5 # Anyresult
test6 # Pass

【讨论】:

  • 我不想要test6之前的空间
  • 如果你想要它消失,不难弄清楚如何删除空间。只需添加另一个管道并插入 sed 's/\s//' 我将添加回答。
  • 实际上这个结果我是以 html 格式发送的。所以我用
    替换了 \n ,这样它就可以正确地覆盖他们。但在执行后:` echo "fOO:pass,tesT2:fail,TESt:passS,fdfdhfd:pass,test5:anyresult test,test6:pass asfas" | sed -E 's/:/#/g;s/,/ /g;s/(.\S*)(#)(.)(\S*)\s/\1 \2 \U\3\ L\4
    /g;' | awk 'NF 3 { $1=""}1' | sed 's/\s//'` 我得到的输出缺少第一个测试的名称,我得到的输出如下:# Pass&lt;br&gt;tesT2 # Fail&lt;br&gt;TESt # Pass&lt;br&gt;fdfdhfd # Pass&lt;br&gt;test5 # Anyresult&lt;br&gt;test test6 # Pass&lt;br&gt;asfas
  • @SameerAtharkar 那是因为您更改了输出,所以awk 正在删除第 1 列,因为结果现在是一行。您需要多行输出还是单行输出?如果多行但末尾带有&lt;br&gt;,则只需将换行符\n 返回到
    之后的命令
  • 我可以通过以下方式实现它:echo "fOO:paSS,tesT2:fail,TESt:pasS,fdfdhfd:pass,test5:anyresult test,test6:pass asfas" | sed -E 's/:/#/g;s/,/ /g;s/(.\S*)(#)(.)(\S*)\s/\1 \2 \U\3\L\4&lt;br&gt;\n/g;' | awk 'NF &lt; 2 || NF &gt; 3 { $1=""}1' | sed 's/\s//' 你能简要解释一下到底发生了什么吗?
【解决方案3】:

我不禁认为,使用 Awk 一定要容易得多。

awk BEGIN { RS=','; FS=':' }
NF > 2 { print $1 " # " (tolower($2)s~ /^(test/fail)$/ ? toupper(substr($2, 1, 1)) tolower(substr($2, 2)) : $2) }'

【讨论】:

  • 我不得不猜测或推测一些事情,因为您的要求并不详尽。为什么根本不打印最后一个输出?为什么“任何东西”在您想要的输出中大写?也许仍然编辑您的问题以澄清这些细节。
猜你喜欢
  • 2019-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-16
  • 1970-01-01
  • 2016-10-30
  • 1970-01-01
相关资源
最近更新 更多