我有一个如下所示的格式:
983243 woiewewrsadhjf 234
093111 srewdslkjfdgdsdsf 111
我可以使用 sed 搜索第三个字段中文本的所有实例并仅更改那些实例,同时保留其他第三个字段不变吗?因此,在第三个字段中搜索 111,将所有包含 111 的第三个字段更改为其他文本,而其他第三个字段(例如 234)保持原样。
如果可能的话,你们可以分解这个解决方案,这样我就可以了解命令是如何形成的。我是来学习的。
答案1
如果不是必须的sed
,这里有一个awk
解决方案:
awk '$3=="111"{$3="othertext"}1' input.txt
对于每一行,这将检查第三个字段(默认情况下被识别为空格分隔的字符组)是否相等111
,如果是,则将其设置为othertext
。如果您的输入数据使用不同的分隔符(例如TAB
),则必须使用-F
命令行选项(例如awk -F'\t' '....'
)来指定。
1
规则块的外部({ ... }
或实际上任何评估为“真”/非零的条件)指示awk
打印当前行,包括所做的所有修改。这样,不需要更改的行将“按原样”打印。
需要注意的是:awk
将使用内部存储为变量的“输出字段分隔符”重新组装那些需要从各个字段更改的行,OFS
该变量默认为单个空格。这通常没有问题,但如果您的列由多个空格分隔,这些分隔符将(默认情况下)被解释为仅一张单曲输入分隔符,因此这些行将在输出中显示为更改后的字段分隔。
答案2
处理字段的方式sed
如图所示。首先,我们通过使用已知不存在于模式空间中的字符(即记录分隔符)将其隔离来标记第三个非空间块\n
。那么如果替换成功=>第三个字段中有111。否则我们删除换行符。
我们正在使用打开的GNU sed
扩展正则表达式标志。-E
$ sed -Ee '
s/\S+/\n&\n/3
s/\n111\n/otherwise/
s/\n//g
' file
Posixly我们这样做:
$ sed -e '
s/[^[:space:]]\{1,\}/\
&\
/3
s/\n111\n/otherwise/
s/\n//g
' file
答案3
echo '093111 srewdslkjfdgdsdsf 111' | sed 's/\(.*\) \(.*\) \(111\)/\1 \2 othertext/'
这就是你想要的。
请注意,您正在搜索的文本(本例中为 111)不包含特殊字符,例如\
,.
或*
。在这种情况下,他们需要逃脱。
解释
匹配.
任何字符。
*
表示前一个原子的零次或多次重复。
因此,当我们写入时,.*
我们将匹配任何字符序列。在大多数情况下 sed 是贪婪的,这意味着它将尝试匹配它可以匹配的最大序列。但由于我们要求下一个字符是空格,因此.*
当它找到它时将完成匹配。
使用基本正则表达式(sed 中的默认值),我们可以使用\(
和\)
来分隔不同的原子。我们用它们来标记 3 个原子。
在命令的第二部分中,\n
表示“位置 n 的原子”。我们使用第一个和第二个,但我们用我们需要的任何文本替换第三个。
注意:当使用字段(用空格分隔)时,使用 awk 通常更容易:
echo '093111 srewdslkjfdgdsdsf 111' | awk '{if ($3 == "111") $3 = "othertext"; print}'