我有一个这样的文件:
1,2,subjects,\mat\hs,unix\,\Nato,\N,123,\N
我想用 # 替换所有出现的 \,除了 \N,这样输出如下所示:
1,2,subjects,#mat#hs,unix#,#Nato,\N,123,\N
我正在尝试编写一个 sed 命令,它看起来像-
sed -e 's@\\([^N])@#\1/g' filename
但是对于 ex 开头有 \N 的所有值,这都会失败。\Nato
在上面的例子中。
有人可以帮我找出满足我要求的 sed 命令(正则表达式)吗?
答案1
我不太精通sed
。但这可以通过perl
使用正则表达式环视轻松完成:
perl -pe 's/\\(?!N\b)/#/g' your_file_here
这会将修改后的文件打印到标准输出。要进行替换,您可以执行以下操作:
perl -pi -e 's/\\(?!N\b)/#/g' your_file_here
基本上,这会将任何后面未跟的反斜杠N\b
(单词边界处的字符 N)替换为#
。
编辑
如果您绝对确定您的条目是用逗号分隔的,则可以执行此操作来覆盖\N
单词末尾的情况(如SOLEM\N
您提供的示例中所示):
perl -pe ' s/\\/#/g; s/(\A|,)\s*#N\s*(\Z|,)/$1\\N$2/g;' your_file_here
它只是用散列标记替换任何反斜杠,然后#N
在两个逗号之间、字符串开头和逗号之间或逗号和字符串结尾之间查找找到的内容。
答案2
$ echo '1,2,subjects,\mat\hs,unix\,\Nato,\N,123,\N' \
| sed -r -e 's@\\([^N]|N[^,])@#\1@g'
1,2,subjects,#mat#hs,unix#,#Nato,\N,123,\N
编辑对于 \N 作为单词大小写的一部分:(参见注释)
$ echo '1,2,subjects,\mat\hs,unix\,\SOLEM\N,\N,123,\N' \
| sed -r -e 's@,\\N$@,:SINGLE_N_PLACEHOLDER:@g' \
-e 's@^\\N,@:SINGLE_N_PLACEHOLDER:,@g' \
-e 's@,\\N,@,:SINGLE_N_PLACEHOLDER:,@g' \
-e 's@\\@#@g' \
-e 's@:SINGLE_N_PLACEHOLDER:@\\N@g'
1,2,subjects,#mat#hs,unix#,#SOLEM#N,\N,123,\N
这是丑陋且不可靠的(占位符字符串需要是唯一的,如果该模式出现在文本中,将停止工作),但我没有找到一种工作方法来使 sed 使用 PCRE/Perl 支持断言的方式。
你可以像这样缩短它:
$ echo '1,2,subjects,\mat\hs,unix\,\SOLEM\N,\N,123,\N' \
| sed -r -e 's@\\@#@g' \
-e 's@(,|^)#N(,|$)@\1\\N\2@g'
1,2,subjects,#mat#hs,unix#,#SOLEM#N,\N,123,\N
但在本例中,single#N
是不得出现在字符串中的占位符。
答案3
sed -e 's@\\\([^N]\|\(N[a-zA-Z]\|$\)\)@#\1@g' your_file_here
解释:替换所有\
后面的
- 没有什么
N
, - 或
N
后跟任何字母[a-zA-Z]
(如果需要的话可以扩展) - 行结束
with#
和其余的匹配模式。
答案4
$ echo '1,2,subjects,\mat\hs,unix\,\Nato,\N,123,\N' |
sed -r -e 's/\\N/XELI/g' |
sed -e 's/\\/#/g' |
sed -e 's/XELI/\\N/g'
1,2,subjects,#mat#hs,unix#,\Nato,\N,123,\N
我发现将其拆分更具可读性:
- 将 \N 替换为一些不出现的字符,
- 然后将/替换为#
- 并将 /N 替换回来