如何从特定行中删除/?

如何从特定行中删除/?

我有一个如下文件

'ABC'|filler|'Y'|'john/1'|'text'
'ABC'|filler|'Y'|'john/1'|'te/xt'
'ABC'|filler|'N'|'mary/2'|'text'
'DEF'|filler|'N'|'jane/3'|'text'

在最初的 grep 之后,

$ wordY="'Y'|"
$ wordN="'N'|"
$ grep ABC test.txt | grep "$wordY\|$wordN'[[:alpha:]]+/"

正在返回

'ABC'|filler|'Y'|'john/1'|'text'
'ABC'|filler|'Y'|'john/1'|'te/xt'    
'ABC'|filler|'N'|'mary/2'|'text'

我现在希望/仅删除名称并将其保存到新的 .txt 文件

所以我的理想输出是

'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt'    -- / should not be removed for 'te/xt'
'ABC'|filler|'N'|'mary2'|'text'

如何添加到命令中以获取输出?

答案1

假设输入是一个用作|字段分隔符的“简单”CSV 文件,并且没有带有嵌入分隔符或换行符的字段,我们可以使用awk它来寻址我们想要修改的特定字段。

$ awk -F '|' -v sq="'" 'BEGIN { OFS = FS } $1 == sq "ABC" sq { gsub("/","",$4); print } ' file
'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt'
'ABC'|filler|'N'|'mary2'|'text'

我们-F '|'awk输入读取为|分隔字段的换行符分隔记录。由于在内联awk脚本中处理单引号可能很棘手并导致代码不可读,因此我们还将awk变量设置sq为单引号字符。

该代码检测第一个字段的值恰好为 的任何记录'ABC',并且对于这些记录,它会在输出(可能)修改的记录之前删除第四个字段中的所有斜杠。

我们还可以避免对任何第一个字段数据进行硬编码,而只需将我们想要检测的整个字符串传递到变量中(此处为query):

$ awk -F '|' -v query="'ABC'" 'BEGIN { OFS = FS } $1 == query { gsub("/","",$4); print } ' file
'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt'
'ABC'|filler|'N'|'mary2'|'text'

正如下面的评论所指出的(现已删除),您可以可能仅当修改后的记录在第四列中实际包含斜杠时才输出。这可能简化我们的命令有点:

awk -F '|' -v query="'ABC'" 'BEGIN { OFS = FS } $1 == query && gsub("/","",$4)' file

gsub()命令返回已进行的替换数,这意味着它将返回原始第四个字段中存在的斜杠数。如果没有,该函数返回零,这将导致记录不是被打印。

您是否还想确保第三个字段是'Y''N',您可以使用

awk -F '|' -v query="'ABC'" -v yn="^'[YN]'$" '
    BEGIN { OFS = FS }
    $1 == query && $3 ~ yn && gsub("/","",$4)' file

在这里,我们将第三个字段需要匹配的正则表达式传递给变量awkyn然后使用它来$3 ~ yn执行我们的测试。该表达式^'[YN]'$匹配'Y''N'

答案2

使用sed

$ sed -En "\~^('ABC[^YN]*(Y|N)'\|'[[:alpha:]]+)/~s//\1/p" input_file
'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt'
'ABC'|filler|'N'|'mary2'|'text'

答案3

你可以这样做:

$ awk 'BEGIN{FS=OFS="|"; q="\047"} 
       ($1==q"ABC"q)&&($3~q"Y|N"q)&&($4~"/") { sub("/","",$4);print }
      ' test.txt

'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt'
'ABC'|filler|'N'|'mary2'|'text'

它将字段分隔符和输出字段分隔符设置为相同的值:|。然后使用引号字符创建一个变量q="047"(这将简化脚本的其余部分),然后测试 3 件事:

  • 第一个字段完全等于'ABC'
  • 第三个字段是'Y'or 'N'
  • 第四个字段实际上包含一个/.

然后做:

  • /删除第四个字段内的第一个。
  • 打印整行。

这与您在 grep 使用正则表达式测试 ABC 中发布的 grep 命令不同。如果这就是您想要的,则将 替换$1 == q"ABC"q$1 ~ "ABC"或什至只是~"ABC"(这将在整个输入行的任何位置找到 ABC)。

测试所有输入线是否具有其中一个值似乎Y也是多余的。N如果是这样,您可以删除第二个测试。

这可以让 awk 命令简化为:

awk '($1~/ABC/)&&sub("/","",$4)' FS="|" OFS="|" test.txt

如果您需要替换第四个字段中的所有内容,那么您可以使用/更改函数。请注意,某些操作系统(甚至是当前的操作系统)可能会携带subgsub较旧的awk实现这可能不支持 gsub。

答案4

tr适用于此类内容:

grep ABC test.txt | grep "$wordY|$wordN'[[:alpha:]]+/" | tr -d '/'

tr是“translate”的缩写,允许您更改给定集中出现的任何字符,方法是删除该字符,或将其替换为另一个集中相同位置的字符。

-d参数选择“删除字符”模式,其中给定集合中的字符(此处该集合只是一个字符“/”)在重写到输出之前从输入中删除。

有关详细信息,请参阅man tr

相关内容