使用 sed 删除列表中的项目

问题描述 投票:0回答:3

我正在尝试使用 sed 删除以特定方式格式化的文本文件中的列表中的特定项目。我简单举例说明一下;我有...

ITEMS="$ITEM $ITEM1 $ITEM2 $ITEM3"

我想从列表中删除 $ITEM,这样这将变成...

ITEMS="$ITEM1 $ITEM2 $ITEM3"

列表甚至还可以只包含 $ITEM 而没有编号的 $ITEM,例如 ...

ITEMS="$ITEM"

这将变成

ITEMS=""

当然,一旦 $ITEM 被删除。

执行此查找/删除时,不知道列表中存在多少个 $ITEM。所述文本文件除此行之外还包含其他文本,但ITEMS=对于文本文件行的开头是唯一的,即这是唯一以ITEMS=开头的行。所以基本上,我想找到以 ITEMS= 开头的行并从中删除 $ITEM 元素。如何使用 sed 最好地完成此任务?

bash
3个回答
1
投票

$ITEM
前后的空格真的很烦人。 :)

尝试这条线:

sed -r 's/"\$ITEM /"/; s/\$ITEM //g; s/ ?\$ITEM"/"/' file

用一些例子进行测试:

kent$ echo 'ITEMS="$ITEM"'|sed -r 's/"\$ITEM /"/; s/\$ITEM //g; s/ ?\$ITEM"/"/'                                                                                  
ITEMS=""
7pLaptop 20:57:44 /home/kent/myCodes/vim/last256
kent$echo 'ITEMS="$ITEM $ITEM1 $ITEM2 $ITEM $ITEM3 $ITEM"'|sed -r 's/"\$ITEM /"/; s/\$ITEM //g; s/ ?\$ITEM"/"/'
ITEMS="$ITEM1 $ITEM2 $ITEM3"

编辑

对于OP的评论,添加解释。

's/"\$ITEM /"/;     #step1 check if the first element is $ITEM, do sub
s/\$ITEM //g;       #step2 handle the middle elements
s/ ?\$ITEM"/"/'     #step3 handle the last element case. also this handles single ("$ITEM") case.

我使用了 3 个步骤,因为 OP 希望处理后具有相同的格式(单个空格分隔值)。也许有更简单/更好的解决方案,我只是想到了这种方式,分三步进行替换/格式化。 :(


0
投票

我们可以在这里使用正则表达式捕获组的强大功能。这是一个神奇的例子:

$ echo 'ITEM1 ITEM2 ITEM3 ITEM4' | sed -r 's/(.*)( ITEM2|ITEM2( |$))(.*)/\1\4/g'
ITEM1 ITEM3 ITEM4
$ echo 'ITEM1 ITEM2 ITEM3 ITEM4' | sed -r 's/(.*)( ITEM4|ITEM4( |$))(.*)/\1\4/g'
ITEM1 ITEM2 ITEM3
$ echo 'ITEM1 ITEM2 ITEM3 ITEM4' | sed -r 's/(.*)( ITEM4|ITEM4( |$))(.*)/\1\4/g'
ITEM1 ITEM2 ITEM3
$ echo 'ITEM1' | sed -r 's/(.*)( ITEM1|ITEM1( |$))(.*)/\1\4/g'

解释。正则表达式中括号中的部分表示“捕获组”。它们在这里,按特定顺序排列:

  1. .*
    - 我们要删除的项目之前的所有内容。
  2.  $ITEM_TO_DELETE|ITEM_TO_DELETE( |$)
    - 我们要删除的部分。
  3.  |$
    - 我们要删除的项目末尾的空格或 EOL(请注意,该组位于第 2 组中,但仍然是一个单独的组。
  4. .*
  5. - 我们要删除的项目后面的所有内容。
    
    
  6. 请注意,即使该组为空,它仍然有效。

现在是最棘手的部分。第 2 组与以下其中一项比赛:

我们要删除的项目,前面加一个空格
  • 我们要删除的项目,后跟空格或行尾。
  • 所以基本上我们要做的就是删除组 2(连同其中包含的组 3)并仅保留组 1 和 4。这是 sed 命令负责的部分:
\1\4

sed 表达式的一般表示如下:

"s/(.*)( $ITEM|$ITEM( |$))(.*)/\1\4/g"

其中 
$ITEM

是包含我们要删除的项目的变量。

    


-2
投票

echo 'a list of words' | sed 's/\<list\>//g'

© www.soinside.com 2019 - 2024. All rights reserved.