Как я могу использовать sed, чтобы исключить шаблоны при объединении линий? - PullRequest
0 голосов
/ 15 января 2020

Я пытаюсь использовать sed для поиска строк, которые начинаются с «1», и соединить их следующей строкой, игнорируя строки, начинающиеся с «1». мой исходный файл выглядит так:

name  cat 
1 
7.75 
2 
1.27 
X 
5.10 

Требуемый вывод:

name  cat 
1 7.75 
2 
1.27 
X 
5.10 

У меня есть команда, которая ищет строки, которые начинаются с 1, и присоединяется к следующей строке, однако, потому что У меня также есть строки с 1. *, которые я хочу игнорировать. Я пробовал следующую команду sed и использовал, чтобы попытаться игнорировать десятичные дроби, однако она не работает. Команда, которую я использую:

sed '/^\<1\>/N;s/\n/ /'

, но она дает такой вывод:

name  cat 
1  7.75 
2 
1.27  X 
5.10 

Как мне соединить строки, начинающиеся с '1', со следующей строкой, игнорируя строки, которые начать с 1. *?

Редактировать:

  • Я хочу объединить только строки, содержащие '1' (ничего больше в строке), со следующей строкой
  • Некоторые строки начинаются с плавающей запятой, например 1.2, я хочу их игнорировать, чтобы следующая строка не добавлялась к этому.

Ответы [ 4 ]

1 голос
/ 15 января 2020

Использование любого awk в любой оболочке на каждом UNIX поле:

$ awk '{printf "%s%s", $0, ($1==1"" ? OFS : ORS)}' file
name  cat
1  7.75
2
1.27
X
5.10

К вашему сведению, некоторые (все?) Решения sed, опубликованные до сих пор, используют не-1004 * POSIX функциональность и так YMMV в зависимости от того, что они делают, в зависимости от того, какой седь вы используете.

1 голос
/ 15 января 2020

Не могли бы вы попробовать следующее.

awk '
$0==1{
  prev=$0
  next
}
prev{
  $0=prev OFS $0
  prev=""
}
1
END{
  if(prev){
    print prev
  }
}
' Input_file

Объяснение: Добавление подробного объяснения для вышеуказанного кода.

awk '                ##Starting awk program from here.
$0==1{               ##Checking condition if line is having 1 value then do following.
  prev=$0            ##Creating variable prev and set its value to current line value.
  next               ##next will skip all further statements from here.
}
prev{                ##Checking condition if prev variable is NOT NULL then do following.
  $0=prev OFS $0     ##Setting current line value to prev OFS and current line.
  prev=""            ##Nullifing variable prev here.
}
1                    ##1 will print the edited/non-edited line here.
END{                 ##Starting END block for this awk program here.
  if(prev){          ##Checking condition if variable prev is NOT NULL then do following.
    print prev       ##Printing variable prev here.
  }                  ##Closing BLOCK for if condition here.
}                    ##Closing END block of this awk program here.
' Input_file         ##Mentioning Input_file here.

Вывод будет быть следующим.

1  7.75
2
1.27
X
5.10
1 голос
/ 15 января 2020
sed '/^1/{/^1\./!N;s/\n/ /}'

Если строка начинается с 1, то, если она не начинается с 1., добавьте следующую строку. Затем замените символ новой строки пробелом.

Или просто:

sed '/^1\([^\.]\|$\)/N;s/\n/ /'
# same without `\(\|\)`
sed '/^1[^\.]/N;/^1$/N;s/\n/ /'

Если строка начинается с 1, а затем содержит что-то еще, кроме запятой или конца строки, затем добавьте следующую строку. Замените новую строку пробелом

Я хочу объединить только строки, содержащие '1' (ничего больше в строке), следующей строкой

Так что просто сопоставьте 1.

sed '/^1$/N;s/\n/ /'

Может быть, вы хотите просто сопоставить 1 с последующим пробелом?

sed '/^1[[:space:]]*$/N;s/\n/ /'

Или только пробелами?

sed '/^1 *$/N;s/\n/ /'

Sed - Введение и учебное пособие Брюса Барнетта - отличное место, чтобы научиться использовать sed. Чтобы выучить регулярные выражения, я рекомендую играть с кроссвордами регулярных выражений , они позволяют быстро и весело выучить регулярные выражения.

1 голос
/ 15 января 2020

Вы можете начать свой сценарий sed, начав новый цикл, когда строка начинается с 1.:

#!/bin/sed -f

/^1\./n   # don't change 1.x
/^1\b/N   # \b is GNU sed word-boundary
s/\n/ /

Таким образом, только строки, не начинающиеся 1., добавляют следующую строку.

Пример вывода:

name  cat 
1  7.75 
2 
1.27 
X 
5.10

Согласно последующим комментариям по этому вопросу, кажется, что вы хотите объединить только строки, содержащие 1 и дополнительные конечные пробелы, что делает сценарий намного проще:

#!/bin/sed -f

/^1[[:space:]]*$/N   # match the whole line
y/\n/ /
...