xxxxxx15 |xxxxxx02|RM99999 |xxxxxx |安库尔 |xxxxx |xxxxxxxx|M|xxxxxxxx| | | |xxxxxxx|xxx|xxxxxxxx| |10 |纽约| 23.00|周五|下午| | |不适用
想把10换成65,我衣柜里有的是sed -i '/^.\{20\}RM99999/ s/^\(?:[^|]*\|\)\{16\}\([^|]*\)/\165/' test.txt
但它用 65 替换第一个字符(可以在更多位置,但需要替换第 20 个字符RM99999
的行)RM99999
答案1
看起来像一个 XY 问题。
为什么不尝试使用 awk 呢?
awk -F\| -v OFS=\| '$3=="RM99999" && $17 == 10 { $17=65 } {print ; } '
在哪里
-F\|
告诉 awk 使用 |作为字段分隔符(\
告诉 shell 转义|
)-v OFS=\|
告诉 awk 使用 |作为输出记录时的字段分隔符$3=="RM99999" && $17 == 10
选择第三行为 RM99999,第十七行为 10$17 = 65
替换为 65{ print ; }
打印所有已更改和未更改的图案
答案2
sed '/^.\{19\}RM99999/s/10/65/' <in >out
将替换字符串第一次出现的位置10用字符串65在字符串所在的行上RM99999从第 20 个字符开始。
我猜有些人认为第 17 字段应该被替换。我真的不明白为什么,因为我在问题中看不到它,但如果这是你想要的......
sed '/^.\{19\}RM99999/s/[^|]*/65/17' <in >out
...这将|
用字符串替换第 17 个分隔字段65在字符串所在的行上RM99999从第 20 个字符开始。
我只是在抓救命稻草,但也许它们的意思只是 10 并且只在第 17 场,并且只在RM99999从 20 个字符开始?有点难了...
sed -e'/^.\{19\}RM99999/s/|/|\n/16' \
-e's/\n\([^|]*\)10/\165/;s/\n//' <in >out
...但是这样就可以了。仔细想想,确实看起来一点更像是你自己的代码。也许这就是我们最终想要的。
这个比较直接一点...
sed -e'/^.\{19\}RM99999/!b' \
-e's/|\([^|]*10\)*/&\n/16' \
-e's/10\n/65/;s/\n//'
如果字段数是固定的,那么这一步就能完成。
sed -e'/^.\{19\}RM99999/s/10\([^|]*\(|[^|]*\)\{7\}\)$/65\1/'
当然,你可以从前端做同样的事情......
sed -e'/^.\{19\}RM99999/s/^\([^|]*\(|[^|]*\)\{16\}\)10/\165/'
但由于尾部的字段数量只有一半,如果有帮助的话,最好不要这样做。
使用扩展正则表达式语法编写起来更容易一些:
sed -Ee'/^.{19}RM99999/s/10([^|]*(\|[^|]*){7})$/65\1/'