我已经能够从固定长度文件中删除第一列中出现的所有特殊字符,但结果是所有后续列都向左移动了删除的字符数。它是一个空格分隔的文件。输入文件中的第 1 行已损坏。第 2 行应该是这样的。字符串 000022000362700 在两行中均从位置 49 开始。我遇到的问题是,删除 3 个特殊字符后,该字段移动到位置 46。
GAVISCON 液体薄荷 ÎOT 000022000362700 159588000007979400 50001584182 0006S020000 GAVISCON 液体薄荷 OT 000022000362700 159588000007979400 50001584182 0006S020000
我正在使用的命令如下:
cat file.txt | grep '[^ - ~]' | sed's/[^ - ~]//g'
这会产生以下输出:
GAVISCON LIQUID PEPPERMINT OT 000022000362700 159588000007979400 50001584182 0006S020000
通过删除特殊字符,已更改字段右侧的每个字段都已移至左侧,从而更改了字段起始位置。
我已经搜索了一段时间,但找不到解决此问题的任何方法。
我应该如何进行?
答案1
使用这个命令:
sed -r 's/(\^|-|~)/ /g' file.txt
sed -r
-r, --regexp-extended
在脚本中使用扩展正则表达式/ /
空格作为字段分隔符(或任何其他字符串)(\^|-|~)
第一捕获组
(\^|-|~)
第一种选择:
\^
\^
^
字面匹配字符第二种选择:
-
-
-
字面匹配字符第三种选择:
~
~
~
字面匹配字符
另一种变体是这样的(Thx@科斯塔斯):
sed 's/[-~^]/ /g' file.txt
[^-~]
[-~^]
匹配下面列表中存在的单个字符-~^
列表中的单个-~^
字符
答案2
sed's/[^ - ~]//g'
可能不是您使用的命令,因为它只会抱怨无效的命令。永远复制粘贴!
我猜你真的跑了sed 's/[^ -~]//g'
。这会将任何不是可打印 ASCII 字符的字符替换为空字符串。换句话说,这将删除所有不可打印 ASCII 字符的字符。 (请注意,这在默认区域设置中是正确的,即在 下LC_ALL=C
,但在许多其他区域设置中并非如此。)
要保持列对齐,请将每个不可打印字符替换为空格。
sed 's/[^ -~]/ /g'
由于您的grep
命令,只有包含不可打印字符的行才会出现在输出中。你不需要那个grep
。将所有行传递给sed
;不需要修改的行将出现在输出中的正确位置。
<file.txt LC_ALL=C sed 's/[^ -~]/ /g' >new-file.txt
这会在列中间添加空格,例如您最终会得到
GAVISCON LIQUID PEPPERMINT OT 000022000362700 159588000007979400 50001584182 0006S020000
如果您希望空格结束在列的右侧,即
GAVISCON LIQUID PEPPERMINT OT 000022000362700 159588000007979400 50001584182 0006S020000
您将需要一种不同的方法,您可以在其中指示列的停止位置。虽然这可以在 sed 中完成,但在 awk 中要容易得多。以下是如何从第一列中删除不可打印的字符并保留从位置 49 开始的其他列中的数据。
<file.txt LC_ALL=C awk '{
first_column = substr($0, 1, 48);
gsub(/[^ -~]/, "", first_column);
printf "%-48s%s\n", first_column, substr($0, 49)
}' >new-file.txt