![Shell 脚本删除特定位置的特定字符](https://linux22.com/image/211773/Shell%20%E8%84%9A%E6%9C%AC%E5%88%A0%E9%99%A4%E7%89%B9%E5%AE%9A%E4%BD%8D%E7%BD%AE%E7%9A%84%E7%89%B9%E5%AE%9A%E5%AD%97%E7%AC%A6.png)
请假设以下数据。为了便于理解,我使用下面的第 29 列位置我想检查位置 29 是否以字母或数字开头。例如,如果需要删除第一行中的字母“U”,则需要删除第二行“D”,并且第三行由于其以数字开头而无需执行任何操作
47720920010500002 U314178
37966744783100812 D123455
37966880762200334 356678
我尝试了以下方法
sed 's/^\(.\{212\}\)U/\&/' $file_name
...用空格替换第 212 个字符“U”。
cut -c -211,213- $file_name
...从第 212 个位置删除空格
如果其常量 U ,则此代码应该可以工作。需要一些命令帮助(如果有的话)来检查 az 中的所有 aplhabets
答案1
您与您的关系密切:
sed 's/^\(.\{212\}\)U/\&/' $file_name
您确实使用 捕获了前 212 个字符\(...\)
。您所要做的就是\1
在替换中引用该内容。&
会将其替换为整个匹配的文本,包括U
.\&
替换为文字&
。
另外,如果您要删除的是第 212 个字符,那么您要匹配的是之前的 211 个字符,而不是 212 个字符。
所以:
sed 's/^\(.\{211\}\)U/\1/' < "$file_name"
或者:
sed -- 's/^\(.\{211\}\)U/\1/' "$file_name"
(还添加了缺少的引号$file_name
,并显示了两种不同的方法来防止以开头的文件名-
(第一个更好,因为它也适用于名为的文件,并且如果无法打开文件则-
避免运行))sed
替换U
为[[:alpha:]]
匹配任何单个字母(嗯,人类语言脚本中使用的图形符号不是标点符号)。或者[[:upper:]]
对于任何大写字母,或者仅对于 ASCII 字母(不,这与通常还包含诸如 之类的字符,甚至在某些语言环境中甚至可能包含诸如/ 之类的多字符整理元素[ABCDEFGHIJKLMNOPQRSTUVWXYZ]
不同)。[A-Z]
Æ
Ê
DZS
Dzs
答案2
awk
可以测试和切割:
awk '! /^[[:alpha:]]/ { print; next; }
{ print substr ($0, 1, 211) substr ($0, 213); }'
对较短的数据进行测试(删除第四个位置)。
答案3
使用任何 POSIX awk:
$ awk 'substr($0,29,1) ~ /[[:alpha:]]/{ $0=substr($0,1,28) substr($0,30) } 1' file
47720920010500002 314178
37966744783100812 123455
37966880762200334 356678
答案4
使用乐(以前称为 Perl_6)
raku -pe 's/ ^ .**28 <(<alpha>)> //;'
或者
raku -pe 's/ ^ .**28 <(<:L>)> //;'
上面检测前 28 个字符之后的第 29 个字母是否是<alpha>
(第一个示例)或<:L>
(Unicode 字母,第二个示例)。字符类<:L>
是 的缩写<:Letter>
,两者都可以使用。
从技术上讲,<alpha>
匹配字母字符加下划线 (_)。另一方面,<:L>
字符类使用 Unicode 通用类别名称。
上面的正则表达式使用捕获标记,<(
... ,将识别的元素删除到OP 希望省略的/字符)>
之外。<alpha>
<:L>
输入示例:
47720920010500002 U314178
37966744783100812 D123455
37966880762200334 356678
示例输出:
47720920010500002 314178
37966744783100812 123455
37966880762200334 356678