在特定位置插入字符串(定长文件)
Insert a string at a specific position (fixed length file)
我试图在固定长度文件的每行中的 80 位置插入一个字符串 "abcd"。
输入文件
1212121212121212121213231232345 00000003088 234235235321 MISS WAN
1212121212121212121213231232345 00000003088 324556346366 MISS NISCH
1212121212121212121213231232345 00000003088 547478657588 MISS RACHEL
1212121212121212121213231232345 00000009781 313156475788 MR & MRS ROCK
每条记录的长度是
awk '{print length}' temp.txt
74
76
77
79
我无法在 80 处插入数据,我尝试了以下命令
sed "s/.\{80\}/&abcd/" test.txt
awk -vFS="" -vOFS="" '{="abcd"}1' test.txt
我想我应该先增加记录的长度,然后我才能使用上面的命令..
要插入空格
sed -e "s/.\{75\}/& /g" test.txt
sed 's/$/ /" test.txt
循环内
while read line
do
printf "$line " >>temp.txt
done <test.txt
大多数情况下,上面的空格会被下一行修改,并且丢失了一些内容,如下所示..
4044046160710301740053062257440 00000003088 850052246976 MISS WAN
046160710301740053062257440 00000003088 850052246976 MISS NISCH
046160710301740053062257440 00000003088 850052246976 MISS RACHEL
2011888360797600140053062257440 00000009781 851011576287 MR & MRS ROCK
预期答案:
4044046160710301740053062257440 00000003088 850052246976 MISS WAN abcd
4044046160710301740053062257440 00000003088 850052246976 MISS NISCH abcd
4044046160710301740053062257440 00000003088 850052246976 MISS RACHEL abcd
2011888360797600140053062257440 00000009781 851011576287 MR & MRS ROCK abcd
任何关于正确答案的指南将不胜感激。
您可以使用gnu awk
命令:
awk -v RS='\r?\n' -v p='80' -v s='abcd' '{
pad=""; for (i=length(); i<=p; i++) pad=pad " "; print [=10=] pad s}' file
1212121212121212121213231232345 00000003088 234235235321 MISS WAN abcd
1212121212121212121213231232345 00000003088 324556346366 MISS NISCH abcd
1212121212121212121213231232345 00000003088 547478657588 MISS RACHEL abcd
1212121212121212121213231232345 00000009781 313156475788 MR & MRS ROCK abcd
注意使用 -v RS='\r?\n'
将记录分隔符设置为可选 \r
,后跟 \n
。这是为了解决输入文件有 DOS 换行符的情况。
For 循环从每一行的长度开始到所需位置(从变量 p
中的命令行传递)并在 pad
变量中附加一个 space。最后我们打印每一行,然后是填充的 space 和新字符串。
根据 OP 要求按长度 80 添加空格的解决方案:
如果您的 Input_files 中有控制 M 字符并且您想删除它们,请使用:
tr -d '\r' < Input_file > temp_file && mv temp_file Input_file
然后 运行 以下代码:
awk -v var="80" '{printf("%s%"var-length([=11=])+1"s%s\n",[=11=],OFS,"abcd")}' Input_file
第二个解决方案(更通用的一个): 你能试试下面的方法吗,这个解决方案将在整个 Input_file 并将根据它添加空格,新输入的最后一个字段将与所有其他行对齐。
awk '
FNR==NR{
len=length([=12=])>len?length([=12=]):len
next
}
{
printf("%s%"len-length([=12=])+1"s%s\n",[=12=],OFS,"abcd")
}
' Input_file Input_file
更简单awk
$ awk '{printf "%-80s%s\n",[=10=],"abcd"}' file
1212121212121212121213231232345 00000003088 234235235321 MISS WAN abcd
1212121212121212121213231232345 00000003088 324556346366 MISS NISCH abcd
1212121212121212121213231232345 00000003088 547478657588 MISS RACHEL abcd
1212121212121212121213231232345 00000009781 313156475788 MR & MRS ROCK abcd
另一种方式,结合 karakfa 的 awk 行,并使用 GNU wc
来获得最大行长度。
file="./your_file"
awk -v sp=4 -v max="$(wc -L "$file")" '{printf "%-"max+sp"s%s\n",[=10=],"abcd"}' "$file"
-v
选项使用文件中的最大行长度初始化变量 max
,sp
用于最大行长度后使用的空格数。
输出:
4044046160710301740053062257440 00000003088 850052246976 MISS WAN abcd
046160710301740053062257440 00000003088 850052246976 MISS NISCH abcd
046160710301740053062257440 00000003088 850052246976 MISS RACHEL abcd
2011888360797600140053062257440 00000009781 851011576287 MR & MRS ROCK abcd
我看不出你在哪里卡住了
sed "s/$/ /" test.txt
和 sed "s/.\{80\}/&abcd/" test.txt
。
你是如何结合它们的?您不希望第一个命令使用 -i
,那会修改输入文件。
不正确的是
# error, did you try this:
sed "s/$/ /" test.txt | sed "s/.\{80\}/&abcd/" test.txt
第二个sed
不会看第一个命令的输出,而是从原来的test.txt
开始。
您可以将它们(我也使用单引号)与
sed 's/$/ /' test.txt | sed 's/.\{80\}/&abcd/'
or shorter
sed 's/$/ /;s/.\{80\}/&abcd/' test.txt
结果可能看起来不错,但您可以在 abcd
之后添加额外的空格。更好的是
sed -r 's/$/ /;s/(.{80}).*/abcd/' test.txt
命令的第一部分很难看。
你可以像
这样写你自己的循环
while IFS= read -r line; do
printf "%-80sabcd\n" "${line}"
done < test.txt
这是一个困难的方法,您可以使用@karakfa 给出的简单 awk
。
我试图在固定长度文件的每行中的 80 位置插入一个字符串 "abcd"。
输入文件
1212121212121212121213231232345 00000003088 234235235321 MISS WAN
1212121212121212121213231232345 00000003088 324556346366 MISS NISCH
1212121212121212121213231232345 00000003088 547478657588 MISS RACHEL
1212121212121212121213231232345 00000009781 313156475788 MR & MRS ROCK
每条记录的长度是
awk '{print length}' temp.txt
74
76
77
79
我无法在 80 处插入数据,我尝试了以下命令
sed "s/.\{80\}/&abcd/" test.txt
awk -vFS="" -vOFS="" '{="abcd"}1' test.txt
我想我应该先增加记录的长度,然后我才能使用上面的命令..
要插入空格
sed -e "s/.\{75\}/& /g" test.txt
sed 's/$/ /" test.txt
循环内
while read line
do
printf "$line " >>temp.txt
done <test.txt
大多数情况下,上面的空格会被下一行修改,并且丢失了一些内容,如下所示..
4044046160710301740053062257440 00000003088 850052246976 MISS WAN
046160710301740053062257440 00000003088 850052246976 MISS NISCH
046160710301740053062257440 00000003088 850052246976 MISS RACHEL
2011888360797600140053062257440 00000009781 851011576287 MR & MRS ROCK
预期答案:
4044046160710301740053062257440 00000003088 850052246976 MISS WAN abcd
4044046160710301740053062257440 00000003088 850052246976 MISS NISCH abcd
4044046160710301740053062257440 00000003088 850052246976 MISS RACHEL abcd
2011888360797600140053062257440 00000009781 851011576287 MR & MRS ROCK abcd
任何关于正确答案的指南将不胜感激。
您可以使用gnu awk
命令:
awk -v RS='\r?\n' -v p='80' -v s='abcd' '{
pad=""; for (i=length(); i<=p; i++) pad=pad " "; print [=10=] pad s}' file
1212121212121212121213231232345 00000003088 234235235321 MISS WAN abcd
1212121212121212121213231232345 00000003088 324556346366 MISS NISCH abcd
1212121212121212121213231232345 00000003088 547478657588 MISS RACHEL abcd
1212121212121212121213231232345 00000009781 313156475788 MR & MRS ROCK abcd
注意使用 -v RS='\r?\n'
将记录分隔符设置为可选 \r
,后跟 \n
。这是为了解决输入文件有 DOS 换行符的情况。
For 循环从每一行的长度开始到所需位置(从变量 p
中的命令行传递)并在 pad
变量中附加一个 space。最后我们打印每一行,然后是填充的 space 和新字符串。
根据 OP 要求按长度 80 添加空格的解决方案: 如果您的 Input_files 中有控制 M 字符并且您想删除它们,请使用:
tr -d '\r' < Input_file > temp_file && mv temp_file Input_file
然后 运行 以下代码:
awk -v var="80" '{printf("%s%"var-length([=11=])+1"s%s\n",[=11=],OFS,"abcd")}' Input_file
第二个解决方案(更通用的一个): 你能试试下面的方法吗,这个解决方案将在整个 Input_file 并将根据它添加空格,新输入的最后一个字段将与所有其他行对齐。
awk '
FNR==NR{
len=length([=12=])>len?length([=12=]):len
next
}
{
printf("%s%"len-length([=12=])+1"s%s\n",[=12=],OFS,"abcd")
}
' Input_file Input_file
更简单awk
$ awk '{printf "%-80s%s\n",[=10=],"abcd"}' file
1212121212121212121213231232345 00000003088 234235235321 MISS WAN abcd
1212121212121212121213231232345 00000003088 324556346366 MISS NISCH abcd
1212121212121212121213231232345 00000003088 547478657588 MISS RACHEL abcd
1212121212121212121213231232345 00000009781 313156475788 MR & MRS ROCK abcd
另一种方式,结合 karakfa 的 awk 行,并使用 GNU wc
来获得最大行长度。
file="./your_file"
awk -v sp=4 -v max="$(wc -L "$file")" '{printf "%-"max+sp"s%s\n",[=10=],"abcd"}' "$file"
-v
选项使用文件中的最大行长度初始化变量 max
,sp
用于最大行长度后使用的空格数。
输出:
4044046160710301740053062257440 00000003088 850052246976 MISS WAN abcd
046160710301740053062257440 00000003088 850052246976 MISS NISCH abcd
046160710301740053062257440 00000003088 850052246976 MISS RACHEL abcd
2011888360797600140053062257440 00000009781 851011576287 MR & MRS ROCK abcd
我看不出你在哪里卡住了
sed "s/$/ /" test.txt
和 sed "s/.\{80\}/&abcd/" test.txt
。
你是如何结合它们的?您不希望第一个命令使用 -i
,那会修改输入文件。
不正确的是
# error, did you try this:
sed "s/$/ /" test.txt | sed "s/.\{80\}/&abcd/" test.txt
第二个sed
不会看第一个命令的输出,而是从原来的test.txt
开始。
您可以将它们(我也使用单引号)与
sed 's/$/ /' test.txt | sed 's/.\{80\}/&abcd/'
or shorter
sed 's/$/ /;s/.\{80\}/&abcd/' test.txt
结果可能看起来不错,但您可以在 abcd
之后添加额外的空格。更好的是
sed -r 's/$/ /;s/(.{80}).*/abcd/' test.txt
命令的第一部分很难看。 你可以像
这样写你自己的循环while IFS= read -r line; do
printf "%-80sabcd\n" "${line}"
done < test.txt
这是一个困难的方法,您可以使用@karakfa 给出的简单 awk
。