Добавьте определенное слово в каждую строку

Происходит то, что оболочка каким-то образом интерпретирует * . Убедитесь, что все извлеченные поля всегда правильно цитируются.

5
21.08.2018, 00:50
7 ответов
sed -e '
   /#$/!{
      G
      s/\(.*\)\n\(.*\)/\2\1/
      b
   }
   h
' 
1
27.01.2020, 20:31

Вот мое решение с gnu sed :

sed '/\(.*\)#/{h;:y;n;/\(.*\)#/b;G;s/\(.*\)\n\(.*\)/\2\1/;by}' test.txt

Быстрое объяснение:

  • h копирует текущий буфер в "место хранения"
  • G добавляет "удерживаемое пространство" к текущему буферу (добавляя возврат переноса, который необходимо удалить)
  • : xxx - метки
  • bxxx - gotos. Только "b" идет в конец скрипта
  • n печатает текущий буфер и читает следующую строку

Вот мое решение с bash:

while IFS='' read -r x;do if [[ "$x" = *# ]] ; then if [ "$p" = "$x" ]; then p=''; else p="$x"; x=''; fi ; fi; printf '%s%s\n' "$p" "$x";done < test.txt
3
27.01.2020, 20:31

С gnu sed :

sed -n -e ' /.*#$/ { p; h; b; };' \
       -e '{ H; x; s/[\n[:blank:]]\+/ /; p; s/\(.*#\).*/\1/; h; }' \
        file.txt

Общая идея состоит в том, чтобы сохранить строку ... # в удерживаемом пространстве и добавить ее в начало строки при последующих не ... # строк (в пространстве шаблона).

2
27.01.2020, 20:31

Использование awk :

$ awk '/^[^ ]*#$/ { prefix = $0; print; next } { print prefix, $0 }' file
bbb-ccc-cccc#
bbb-ccc-cccc#    aasdf  asdas asdasa fgdg
bbb-ccc-cccc#    asdfa  asfdas  adfaq  asfa
bbb-ccc-cccc#    afdaf  fafa  fafd  afafa
bbb-ccc-cccc#

Каждая строка печатается с префиксом. Префикс берется из любой строки, которая соответствует шаблону ^ [^ ␣] * # $ , то есть состоит полностью из непробельных символов и заканчивается на # . Такие строки печатаются без дополнительного префикса, и обработка продолжается со следующей строки ввода.

7
27.01.2020, 20:31

Решение Python:

#!/usr/bin/env python
import sys
prefix = ""
with open(sys.argv[1]) as fd:
    for line in fd:
        new_line = line.rstrip()
        if new_line.endswith('#'):
            prefix = new_line
        else:
            new_line = prefix + new_line
        print(new_line)

Тестовый запуск:

$ ./append_word.py input.txt                                       
bbb-ccc-cccc#
bbb-ccc-cccc#   aasdf  asdas asdasa fgdg
bbb-ccc-cccc#   asdfa  asfdas  adfaq  asfa
bbb-ccc-cccc#   afdaf  fafa  fafd  afafa
bbb-ccc-cccc#

Как это работает это просто. Мы читаем файл построчно, удаляя конечные пробелы или символы новой строки с конца. Мы записываем префикс в каждую строку, если эта строка заканчивается символом # . Если строка не заканчивается на # , мы знаем, что эту строку нужно изменить. Наконец, мы печатаем строку независимо от того, была она изменена или нет.

1
27.01.2020, 20:31

С perl :

perl -lpe 'if (/\H+#/) {$word = $&} else {$_ = $word . $_}'

То есть, если мы найдем последовательность непустых символов ( \ H + ), за которым следует # в строке, мы используем это ( $ & - это то, что соответствует регулярному выражению) в качестве слова, которое нужно вставить в начало следующих строк. .

То же самое с awk :

awk '
  match($0, /[^[:blank:]]+#/) {
    word = substr($0, RSTART, RLENGTH)
    print
    next
  }
  {print word $0}'

То же самое с sed (с использованием пространства удержания для хранения слова ):

sed '
  /[^[:blank:]]\{1,\}#/ {
    h; # save the line in the hold space
    s//\
&\
/; # put newlines on each side of the matched word
    s/.*\n\(.*\)\n/\1/; # remove every thing but the word
    x; # swap hold and pattern space so that now the hold
       # space contains the word. And branch off:
    b
  }
  # for the other lines:
  G; # append the hold space to the pattern space
  s/\(.*\)\n\(.*\)/\2\1/; # move the word to the beginning'

Если вы хотите сопоставить только слова # , которые находятся в конце строки, замените # на # $ во всех трех приведенных выше командах.

10
27.01.2020, 20:31

В баш:

#!/bin/bash

# grab one of the lines ending in #
prefix=$(egrep '#$' file | head -1)

cat file | while read line
do
    # if the line ends in a #, just print it
    if [[ $line =~ \#$ ]]
    then
        echo $line
    else
        # print the line prefixed with the $prefix
        printf -- "%s %s\n" "$prefix" "$line"
    fi
done

[[ $line =~ \#$ ]]— регулярное выражение if,то же регулярное выражение, что и в egrep. Если вашей оболочке это не нравится, вы можете заменить его на if egrep -q '#$' <<< line; then.

2
27.01.2020, 20:31

Теги

Похожие вопросы