Appending 0's to a file in unix/bash if the line is less than a fixed length

浪子不回头ぞ 提交于 2021-01-28 13:57:39

问题


I am looking for a way in which to append 0's to the end of multiple lines in a file if they are less than 66 characters in length so that the total line length equals 66.

Here's an example of the file format (... denotes preceding 56 characters):

$cat file1
...1234567891
...123456
...
...12345678

Ideal format:

...1234567891
...1234560000
...0000000000
...1234567800

回答1:


GNU awk solution:

$ awk '{s=$0; while(length(s)<66) s=s "0"; print s}' file1

or even shorter:

$ awk '{while(length<66) $0=$0 "0"}1' file1

with provided input:

$ awk '{while(length<66) $0=$0 "0"}1' file1
...123456789100000000000000000000000000000000000000000000000000000
...123456000000000000000000000000000000000000000000000000000000000
...000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000
...123456780000000000000000000000000000000000000000000000000000000



回答2:


Awk solution:

Sample file input.txt:

ghWuec]UGaEjxQRN4qUe3uyhNmBszZeJq]0A5hZJiI[fQ[8anRKnpoLXWBwfFt300S
0jmyMPlQbSpFf[ZNdQvR]BwuYxgW6zkBYRPC1PwJEowd7[MmeiWp8Pienu1F32
G]nGbsTdvO24e7Ts5cLRIaYy[zOcUHau5Q7slRYmkcx2LTNR46QE]gs7vKPj
Zxr6HwG15YyYZnDvRDibjOKOlpacrU5oZTWhBixY23]yWfbHe4i6ztME

The job:

awk '{ if(length<66) printf "%s%0*d\n",$0,66-length,0; else print }' input.txt

The output:

ghWuec]UGaEjxQRN4qUe3uyhNmBszZeJq]0A5hZJiI[fQ[8anRKnpoLXWBwfFt300S
0jmyMPlQbSpFf[ZNdQvR]BwuYxgW6zkBYRPC1PwJEowd7[MmeiWp8Pienu1F320000
G]nGbsTdvO24e7Ts5cLRIaYy[zOcUHau5Q7slRYmkcx2LTNR46QE]gs7vKPj000000
Zxr6HwG15YyYZnDvRDibjOKOlpacrU5oZTWhBixY23]yWfbHe4i6ztME0000000000

The same could be shortened to:

awk 'length<66{ printf "%s%0*d\n",$0,66-length,0;next }1' input.txt



回答3:


Pseudo code:

read line by line
    while (line.length < characterNum + prefixLength)
        line += '0';
    add the line to dynamic array
make a new file with the same name (it will replace the previous one)
write data from array to the new file

characterNum is the number of needed characters, in your case 66, prefixLength is 3 in your case("...")

Instead of using dynamic array you can write lines to a new file (with a different name) right after while loop, this will save space.




回答4:


Here's a Python one-liner.

Test data

$ cat test
12345678aaaaaaaaaaaaaaaaaaaaaaa
123

33333333

Python 3

$ python3 -c 'for l in open("test"):print(l.rstrip().ljust(66,"0"))'
12345678aaaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000
123000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000
333333330000000000000000000000000000000000000000000000000000000000

Python 2

$ python -c 'for l in open("test"):print l.rstrip().ljust(66,"0")'
12345678aaaaaaaaaaaaaaaaaaaaaaa00000000000000000000000000000000000
123000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000
333333330000000000000000000000000000000000000000000000000000000000

In order to change the actual file, direct the output to a temporary file and override the original in the end:

$ python ... > newfile && mv newfile test



回答5:


awk '{printf $0; for(i=66; i>length; i--){printf "0"} printf "\n"}' file

Input:

1234567891
123456
123
12345678

Output:

123456789100000000000000000000000000000000000000000000000000000000
123456000000000000000000000000000000000000000000000000000000000000
123000000000000000000000000000000000000000000000000000000000000000
123456780000000000000000000000000000000000000000000000000000000000



回答6:


Could you please try following awk solution too, it will not have any loop into it.

awk '{$0=sprintf("%066d",$0);match($0,/0[^(1-9)]*/);print substr($0,RLENGTH+1)substr($0,RSTART,RLENGTH)}'  Input_file

Adding a non-one liner form of solution too now.

awk '{
$0=sprintf("%066d",$0);
match($0,/0[^(1-9)]*/);
print substr($0,RLENGTH+1)substr($0,RSTART,RLENGTH)
}
'   Input_file

Let's say following is Input_file:

1234567891
123456
12345678

Then after running code output will be as follows.

123456789100000000000000000000000000000000000000000000000000000000
123456000000000000000000000000000000000000000000000000000000000000
123456780000000000000000000000000000000000000000000000000000000000

Explanation:

awk '{
$0=sprintf("%066d",$0);##Re-phrasing current line by adding necessary zeros in front of each line if its length is lesser than 66, %066d will take care of length.
match($0,/0[^(1-9)]*/);##using match for matching regex where it will match from first zero to till a non-zero value comes, so basically it collects all added 0s.
print substr($0,RLENGTH+1)substr($0,RSTART,RLENGTH)##Now printing the substring of 1st from starting of RLENGTH and another substring which will print from RSTART to RLENGTH, now important thing here is what are RLENGTH and RSTART, these are awk out of the box variables which will be set when a regex match is found from match where RSTART re-presents the first index number of matched regex and RLENGTH re-presents the length of matched regex.
}
' Input_file ## Mentioning the Input_file name here.



回答7:


with perl

$ # change 13 to whatever length is needed
$ perl -lne 'print $_ . "0" x (13-length)' ip.txt 
...1234567891
...1234560000
...0000000000
...1234567800
  • $_ contains current line contents without newline character (because of -l option)
  • . will concatenate the two strings
  • x is repetition operator, here it will add as many 0s needed to make line length equal to 13 (lines greater than 13 won't be affected)
  • For inplace editing, use perl -i -lne



回答8:


In pure bash

printf -v A '0%.s0' {1..66};while read B;do B=$B$A;printf '%.66s\n' $B;done<infile


来源:https://stackoverflow.com/questions/46443750/appending-0s-to-a-file-in-unix-bash-if-the-line-is-less-than-a-fixed-length

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!