Вставить строку в определенную позицию (файл фиксированной длины) - PullRequest
1 голос
/ 19 сентября 2019

Я пытаюсь вставить строку «abcd» в позиции 80 в каждой строке файла фиксированной длины.

Входной файл

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="" '{$80=$80"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

Любые указания в направлении вправоОтвет будет высоко ценится.

Ответы [ 5 ]

3 голосов
/ 19 сентября 2019

проще awk

$ awk '{printf "%-80s%s\n",$0,"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
2 голосов
/ 19 сентября 2019

Вы можете использовать команду gnu awk:

awk -v RS='\r?\n' -v p='80' -v s='abcd' '{
    pad=""; for (i=length(); i<=p; i++) pad=pad " "; print $0 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.

Цикл цикла начинается с длины каждой строки до требуемой позиции (передаваемой из командной строки в переменной p) и добавляет пробел в переменной pad,Наконец, мы печатаем каждую строку с последующим пробелом и новой строкой.

1 голос
/ 19 сентября 2019

Решение в соответствии с требованием OP для добавления пробелов длиной 80: Если у вас есть контрольные символы M в ваших файлах Input_ и вы хотите удалить их, используйте:

tr -d '\r' < Input_file > temp_file && mv temp_file Input_file

, затем запустите следующий код:

awk -v var="80" '{printf("%s%"var-length($0)+1"s%s\n",$0,OFS,"abcd")}' Input_file


2-е решение (более общее): Не могли бы вы попробовать следующее, это решение будет искать максимальную длинустрока во всем файле Input_file и добавит пробелы в соответствии с ним, и вновь введенное последнее поле будет выровнено со всеми остальными строками.

awk '
FNR==NR{
  len=length($0)>len?length($0):len
  next
}
{
  printf("%s%"len-length($0)+1"s%s\n",$0,OFS,"abcd")
}
'  Input_file  Input_file
0 голосов
/ 21 сентября 2019

Я не вижу, где вы застряли, используя 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}).*/\1abcd/' test.txt

Первая часть команды безобразна.Вы можете написать свой собственный цикл, например

while IFS= read -r line; do
   printf "%-80sabcd\n" "${line}"
done < test.txt

. Это сложный метод, в котором вы можете использовать простой awk, заданный @ karakfa.

0 голосов
/ 19 сентября 2019

Еще один способ, объединение строки awk karakfa и использование GNU wc для получения максимальной длины строки.

file="./your_file"

awk -v sp=4 -v max="$(wc -L "$file")" '{printf "%-"max+sp"s%s\n",$0,"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
...