Заменить пробелы только после матча в sed или awk - PullRequest
0 голосов
/ 16 февраля 2019

Это набор строк, который мне нужно изменить.

00:00  07:45  01. Alva 
07:45  14:40  02. White Cliffs 
14:40  20:22  03. Ribcage #1 
20:22  25:04  04. I am Oidipus

. После совпадения (которое может быть точкой) мне нужно заменить следующие пробелы (и только те, которые следуют) натире - или подчеркивание _ .

Ожидаемый результат:

00:00  07:45  01._Alva 
07:45  14:40  02._White_Cliffs 
14:40  20:22  03._Ribcage_#1 
20:22  25:04  04._I_am_Oidipus

Я уже пробовал следующее со смешанными результатами ...

dummyfile2 - это имя файла, который я использую для хранения строк текста

sed -i 's/\(\.\)\(\s*\)/\1_/' dummyfile2 | sed -i 's/\(_\)\(\s*\)/\1_/' dummyfile2

дает результат:

00:00  07:45 01._Alva
07:45  14:40 02._WhiteCliffs
14:40  20:22 03._Ribcage #1 
20:22  25:04 04._I am Oidipus

Я также пытался сделать следующее ...

sed -i 's/\(\.\)\(\s*\)/\1_/g' dummyfile2 | sed -i 's/\([[:alpha:]][[:space:]]\)\(\s*\)/_/g' dummyfile2

дает результат:

00:00  07:45 01._Alva
07:45  14:40 02._Whit_Cliffs
14:40  20:22 03._Ribcag_#1 
20:22  25:04 04.__a_Oidipus

Этот последний был ближайшим , который я мог придумать.(Но это не ожидаемый результат.)

Ответы [ 9 ]

0 голосов
/ 17 февраля 2019

Много хороших ответов.Я новичок в awk, но вот одно простое решение

awk 'BEGIN{FS=OFS="  "} {gsub(/ /, "_", $3); print $0}' InputFile

Вот мой InputFile

00:00  07:45  01. Alva
07:45  14:40  02. White Cliffs
14:40  20:22  03. Ribcage #1
20:22  25:04  04. I am Oidipus

, а вот output после awk 'BEGIN{FS=OFS=" "} {gsub(/ /, "_", $3); print $0}' InputFile

00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus

Объяснение: BEGIN = этот блок кода выполняется перед чтением файла, то есть все переменные могут быть объявлены здесь

FS = Разделитель полей = два пробела (распознается новое поле после каждогодва пробела продолжения из InputFile

OFS = Разделитель выходного поля = два пробела (распознается новое поле после каждых двух пробелов продолжения в выходных данных .. Так же, как Inputdata

gsub(/ /, "_", $3), заменяющих одинпробел "" с подчеркиванием _ в столбце 3 ($ 3)

и, наконец, напечатайте каждую строку до конца файла

{print $0}
0 голосов
/ 18 февраля 2019

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

$ perl -pe ' s/(?:\S+)\. (.+)$/$x=$&;$x=~s! !_!g;$x/ge ' whitespace.txt
00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus

$
0 голосов
/ 16 февраля 2019

С процедурным редактированием текста вы можете добиться этого следующим образом:

forEach line {
  select (after ci ".") { findReplace ci " " "_" }
}
0 голосов
/ 16 февраля 2019

Это может работать для вас (GNU sed):

sed -E 's/\s+\</_/3g' file

Заменить третью группу пробелов перед словом и далее на _.

0 голосов
/ 16 февраля 2019

С помощью sed (POSIX-совместимого):

sed -e :a -e 's/\(\.[^ ]*\) /\1_/;ta' file

Если вы хотите заменить последовательные пробелы только одним _:

sed -e :a -e 's/\(\.[^ ]*\)  */\1_/;ta' file
0 голосов
/ 16 февраля 2019

С любым awk в любой оболочке на любой машине UNIX:

$ awk 'p=index($0,"."){tl=substr($0,p+1); gsub(/ /,"_",tl); $0=substr($0,1,p) tl} 1' file
00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus

или с GNU awk за 3-й аргумент для match () и gensub ():

$ awk 'match($0,/([^.]+.)(.*)/,a){$0=a[1] gensub(/ /,"_","g",a[2])} 1' file
00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus
20:22  25:04  05._here_is_a_dot._that_may_hurt._idk.
0 голосов
/ 16 февраля 2019

С GNU sed вы можете сделать это следующим образом:

sed -E ':a;s/(\.\S*)\s+(\S+)/\1_\2/;ta'

Пример (добавлен один крайний регистр):

$ cat file
00:00  07:45  01. Alva
07:45  14:40  02. White Cliffs
14:40  20:22  03. Ribcage #1
20:22  25:04  04. I am Oidipus
20:22  25:04  05.U re  spe   cial

$ sed -E ':a;s/(\.\S*)\s+(\S+)/\1_\2/;ta' file
00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus
20:22  25:04  05.U_re_spe_cial

POSIX sed совместимый:

sed -e ':a' -e 's/\(\.[^[:space:]]*\)[[:space:]][[:space:]]*\([^[:space:]][^[:space:]]*\)/\1_\2/;' -e 'ta' file

Если вы уверены, что в ваших строках нет пробелов или вы хотите заменить пробелы, вы можете удалить вторую группу перехвата ((...) или \(...\)) и \2.

0 голосов
/ 16 февраля 2019

awk на помощь!

$ awk 'BEGIN{FS=OFS="."} {gsub(/ /,"_",$2)}1' file

00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus
0 голосов
/ 16 февраля 2019

РЕДАКТИРОВАТЬ: Похоже, что другие решения позаботятся только о замене пробела на 1-й пробел после ., после чего позаботятся о всех пробелах.

awk 'match($0,/[^.]*/){val=substr($0,RSTART+RLENGTH);gsub(/ /,"_",val);print substr($0,RSTART,RLENGTH) val;next} 1' Input_file

00:00  07:45  01._Alva
07:45  14:40  02._White_Cliffs
14:40  20:22  03._Ribcage_#1
20:22  25:04  04._I_am_Oidipus


Если вы пытаетесь набрать sed, вам может помочь следующее.Вам не нужно использовать несколько команд sed.

sed -E 's/\. +/\._/'  Input_file
00:00  07:45  01._Alva 
07:45  14:40  02._White Cliffs 
14:40  20:22  03._Ribcage #1 
20:22  25:04  04._I am Oidipus

Измените sed -E 's/\. +/\._/' на sed -E 's/\. +/\._/g' выше, если у вас есть несколько вхождений . (пробелы) в строке.



Если вы в порядке с awk, не могли бы вы, пожалуйста, попробовать следующее.

awk '{sub(/\. +/,"._")} 1' Input_file

Если у вас есть несколько случаев ., тогда замените sub на gsub в вышеуказанной команде.Вывод будет следующим:

00:00  07:45  01._Alva 
07:45  14:40  02._White Cliffs 
14:40  20:22  03._Ribcage #1 
20:22  25:04  04._I am Oidipus

Протестированный выше код с несколькими пробелами: Допустим, у нас есть несколько пробелов после ., тогда также будет работать код aboe,Предполагая, что ваш Input_file выглядит следующим образом.

cat Input_file
00:00  07:45  01. Alva 
07:45  14:40  02. White Cliffs 
14:40  20:22  03. Ribcage #1 
20:22  25:04  04.   I am Oidipus

Здесь я изменил последнюю строку, добавив больше пробелов после ., теперь после выполнения кода он заменит их на один _ следующим образом.

awk '{sub(/\. +/,"._")} 1' Input_file
00:00  07:45  01._Alva 
07:45  14:40  02._White Cliffs 
14:40  20:22  03._Ribcage #1 
20:22  25:04  04._I am Oidipus
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...