更新

更新

我有一个平面文件,其中包含表示表中字段的数据列。我从外部源获取该文件,并希望将数据插入到数据库的表中。不幸的是,我收到的文件在特定列中缺少一个字段(添加的新字段)。由于我无法控制发送给我的内容,因此我想编辑文件并仅添加字段。可以sed用于在每一行的特定列中添加文本吗?

例如,假设我有这个文件:

Alan Bradford                 555-2012
Cathy Davies                  555-7823
Edward Farris                 555-9162
Gary Hobbs                    555-5151
Irene Jacobs                  555-1285

该文件缺少区号,所以我想213在前面添加。我知道电话号码总是从第 31 列(纯字符数)开始。所以我希望它显示

Alan Bradford                 213 555-2012
Cathy Davies                  213 555-7823
Edward Farris                 213 555-9162
Gary Hobbs                    213 555-5151
Irene Jacobs                  213 555-1285

我知道我可以通过三遍来完成此操作。我可以使用cut -c1-30并获取第 1 部分,并cut -c31-获取第 2 部分。然后我可以将它们全部粘贴在一起echo "$Part1 $NEWDATA $Part2" >> filename

我只是想知道是否有更简单的方法使用 sed 。我应该能够使用类似的东西

sed -e "30l,i213 " InFile > OutFile

我似乎无法正确理解在行上移动超过 30 个字符,然后插入 的语法213

有人知道什么可能有效,或者比我的剪切和粘贴选项更好吗?

更新

我被告知我的示例不够准确,我应该编辑问题以停止浪费人们的时间。我给出的例子对于这个问题来说非常准确:如何在位置 Y 中始终插入字符串“XXX”,无论它之前或之后是什么?

但没问题......这是我现实世界的例子。我有一个文本文件,每行包含 928 个字符。我想插入一个从位置 878 开始的字符串。字符串前后的值不能每次都相同,因为我要插入的位置后面的下一个字段是备注字段,通常但并非总是如此空白的。

@DonHolgo 的答案最有希望,也是一个很好的答案。但在我的 UNIX (AIX 7.1) 风格中,它似乎只允许您在出现错误之前跟踪最多 255 个字符。

这里我在第 255 列插入“XXX”:

# sed 's/.\{255\}/&XXX /' OrigTextFile
1  030680001001YNPO    14          H502  000595000000000000       1  0000680M00000100000004799000000000000479900000004799000000004799000000000000479900000       SDI42028820                                                         20P561292      00000000000XXX 000000000000000000000000000000000000000000000000000000000000000                                                  T              0000655000000000Y              0000516000000000E              0000280000000000               0000000000000000               0000000000000000               0000000000000000               0000000000000000               0000000000000000               0000000000000000               0000000000000000                                                                                                                                                                                                        20200814

但我尝试在第 256 列或更高列插入相同的操作:

# sed 's/.\{256\}/&XXX /' OrigTextFile
sed: 0602-404 Function s/.\{256\}/&XXX / cannot be parsed.

看起来我的 sed 版本有限制。所以我可能不得不执行我最初的剪切文本文件的计划。 File1 = 文本文件中每行的前 878 个字符 File2 = 我要添加的新字符串,原始文件中每行一行 File3 = 原始文本文件中的剩余字符。

然后加入他们:

# paste File1 File2 File3 > NewTextFile

答案1

您可以使用

sed 's/.\{30\}/&213 /' InFile > OutFile

将前 30 个字符(“任意字符”乘以 30)替换为其自身(&)加上“213”。

答案2

您可以使用计数 RE。例如,x{12}将匹配 12 个x字符,并且y{1,3}将匹配 1、2 或 3 个y字符。这里我们将使用.{30}匹配 30 个字符的通配符(即 30 个任意字符)。结果\1字符串中的 与模式匹配中括号内的引用相匹配

sed -r 's#^(.{30})#\1213 #' file

在您更新的问题中,您现在说插入之前有 878 个字符。因此只需将示例中的 30 修改为现实中的 878 并插入XXX

sed -r 's#^(.{878})#\1XXX#' file

相同的过程可以适用于任何固定宽度的修改。

perl也可以使用,它没有困扰某些实现的行长度限制sed

perl -pe 's#^(.{878})#$1XXX#' file

答案3

您也可以尝试使用awk

awk '{sub(/^.{30}/,"&213 ")}1' file

这将附加213到由该行的前 30 个字符组成的模式,无论它们是什么。

语法如下:

  • sub()函数用于替代首先当前行上出现指定的正则表达式(如果没有明确说明要操作的字符串,则为默认目标)。
  • 正则表达式为^.{30},意思是“任意字符 30 次”,但从行首开始(“锚点” 的意思^)。
  • 替换是“找到的模式( 的含义&),后跟213和 一个空格。
  • 213该行的其余部分将保持不变,从而有效地在前 30 个字符之后插入。

此操作在任何行上执行({ ... }无条件操作块)。 awk然后将打印修改后的行(程序1末尾的awk)。

答案4

如果您遇到了该工具的外部限制,您可以使用另一种方法,将 877 数字分解为 3 个单元,即 255 和剩余的 112。

skip=877
cmax=255
mult=`expr "$skip" / "$cmax"`
rem=`expr "$skip" % "$cmax"`
lim=".\\{$cmax\\}"
re="\\($lim\\)\\{$mult\\}.\\{$rem\\}"

sed -e "s/$re/&XXX/"   your_file_nam

一种更简单的方法是使用Perl

perl -lpe 'substr($_, 877) =~ s/^/XXX/'  your_file_name

Python:

python3 -c '
import sys
f, p, r = sys.argv[1:]
p = int(p)
with open(f) as fh:
  print(*[l[:p]+r+l[p:] for l in fh],sep="",end="") 
' file_name 877 "XXX"

相关内容