Гладкая острота для преобразования списка как “1: 2, 3, 4, 5” к “1.2, 1.3, 1.4, 1.5”

Если Вы хотите включать имя каталога в список, также:

find Essays/ -maxdepth 1
7
24.03.2013, 23:04
7 ответов

Возможно, что-то как:

sed 's/: /./;s/\(\([^.]*\.\)[^,]*\), /\1\
\2/;P;D'

Это - две строки (\<LF> может быть заменен \n с некоторыми sed реализации).

D команда является одним способом реализовать циклы с условием продолжения в sed. Это удаляет первую строку пространства шаблона и, пока существует что-то остающееся в пространстве шаблона, запускается снова и снова с того, что оставляют. Таким образом, вышеупомянутое может быть считано как:

do {
  - change ": " to "." so we start with "23.a, b, c"
  - change "23.x, y, z" to "23.x\n23.y, z"
  - print the first line ("23.x"): P
  - remove it
} while (pattern space is not empty)

Нам не нужно первое s команда, чтобы быть частью цикла, но избежать, что, мы должны были бы использовать более подробный тип цикла как использование маркировок (:) и переходящие команды (b, t).

19
27.01.2020, 20:13
  • 1
    Хороший, но нам нравятся объяснения, из которых код делает... –  Bananguin 24.03.2013, 22:57
  • 2
    Это побеждает для чистого ума. –  Daniel McLaury 24.03.2013, 23:09

Неважно я просто помнил функцию разделения awk, которая делает это довольно простым.

awk -F ":" '{
  split($2, ps, ",");
  for (i in ps) {
    gsub(" ", "",ps[i]);
    print $1 "." ps[i];
  }
}'

(gsub разделяет посторонний пробел.)

Спасибо за другие ответы, все же.

10
27.01.2020, 20:13
  • 1
    я предполагаю то же как @Stephane Chazelas, но больше тупое: awk-F ':' '{gsub (/[^a-z] /"", 2$); gsub (/, + /", \n" дюйм за 1$. ", 2$); gsub (/^\\n / "", 2$); распечатайте 2$}' –  XzKto 25.03.2013, 09:48
  • 2
    Обычно я предпочитаю более сложное FS в таких случаях: awk -F '[:,]' '{for(i=2;i<=NF;i++)printf"%s%s\n",$1,$i}'. –  manatwork 25.03.2013, 12:49
  • 3
    Отметьте это не все awk реализации гарантируют что Ваш i in ps выражение приведет к цикличному выполнению в порядке через массив. Например, mawk делает, но gawk нет. –  manatwork 25.03.2013, 12:52
  • 4
    Это причудливо..., что возможное преимущество там к цикличному выполнению через в другом порядке? –  Daniel McLaury 26.03.2013, 05:44
  • 5
    awkмассивы являются ассоциативными массивами, и ассоциативные массивы обычно работают как этот (например, HashMap в Java, хеше в Perl, dict в Python, Hash в Ruby прежде 1.9.2, выстройте в Tcl). Это вызвано тем, что внутреннее представление данных. Разработка программного обеспечения имеет связанный вопрос, массив assocative заказан?, –  manatwork 26.03.2013, 11:19

Вот Perl один:

 perl -nle '/(.+?):\s*(.+)/; print "$1.$_" for split(/[,\s]+/,$2);' foo.txt

ОБЪЯСНЕНИЕ:

  • perl -nle : это говорит Perl анализировать входной файл одна строка за один раз (-n), выполните сценарий, данный как аргумент -e и добавьте новую строку (\n) к каждой печатной строке (-l).

  • /(.+?):\s*(.+)/ : Соответствуйте первым символам до первого двоеточия, которое сопровождается 0 или больше пробелами (:\s*), затем остальная часть строки. Круглые скобки являются синтаксисом Perl для получения шаблонов, два соответствия сохраняются как $1 и $2.

  • split(/[,\s]*/,$2); : это разделит $2 (второй подобранный шаблон от операции соответствия выше) в , и/или пробелы, создавая анонимный массив.

  • print "$1.$_" for split() : выполните итерации через анонимный массив, созданный разделением выше, сохранив каждого участника массива как $_ и распечатайте его наряду с $1 (первый шаблон, полученный в первом шаге) и точка ..

10
27.01.2020, 20:13
  • 1
    я рекомендую print "$1.$_\n" for ..." вместо map { print "$1.$_\n" } .... –  Christoffer Hammarström 25.03.2013, 14:21
  • 2
    Кроме того, с -l Вам не нужно "\n". Но могло бы быть еще лучше для использования -E и say. –  Christoffer Hammarström 25.03.2013, 14:23
  • 3
    @ChristofferHammarström, интересная рекомендация. Какова причина? А-ч –  manatwork 25.03.2013, 14:24
  • 4
    map сборки и возвраты список значений. Здесь это используется в качестве a for или foreach. –  Christoffer Hammarström 25.03.2013, 14:41
  • 5
    @ChristofferHammarström не забывает это say является новым (жемчуг> =5.10, я думаю), и может не всегда быть доступным. Я использовал map вызовите это - один лайнер, и я хотел его короче. Я понял, что это не улица, законная в отделе CompSci, но это действительно не имеет никакого значения в этом контексте. –  terdon♦ 25.03.2013, 14:41

Вот Ruby один:

ruby -ane '$F.drop(1).each{|f| puts $F.first.gsub(":",".")+f.chomp(",")}' <file.txt

Объяснение

  • рубин-ane: это говорит Ruby auto разделяют строки, один литийne во время, и execute аргумент как сценарий.

  • В автоматическом файле разделения $F массив результата разделения.

  • drop(1) пропускает первое поле (номер строки) и .each циклы по следующим полям.

  • gsub замены : и chomp удаляет запаздывающий разделитель из строки.

5
27.01.2020, 20:13

awk острота, что я думаю, немного более изящна, чем другое awk решение:

awk -F'[:, ]+' '{for(i=2;i<=NF;i++)printf $1"."$i"\n"}' file.in

Это использует в своих интересах то, что awk разделитель полей является regex.

4
27.01.2020, 20:13

Perl:

perl -nE '($first,$rest)=split ": "; say "$first.$_" for split ", ", $rest'

Разделяет строку на первое число и остальных, затем печатает "$first.$_" для каждой из букв.

2
27.01.2020, 20:13

Как насчет простого сценария оболочки Bourne (главным образом):

tr -d ':,' file.txt | while read p r; do for i in $r; do echo "$p.$i"; done; done

Команда "TR" просто чистит двоеточия (:) и запятые () - этот ответ полагается на то, чтобы там быть пробелом в данных (который имеют демонстрационные данные - иначе необходимо использовать sed для преобразования: и, в пробел вместо TR).

Вывод "TR" передается по каналу во внешний цикл, "в то время как считано...; сделайте...; сделанный", который читает строки и повреждает их в два, в первом вхождении пробела (или скорее содержание "$IFS" - разделитель поля ввода оболочки, который значения по умолчанию к пробелу), оставляя префикс в "$p" и остальной части строки в "$r".

Внутренний цикл, "поскольку я в...; сделайте...; сделанный" затем повреждает содержание "$r" в пробеле (" $IFS") и помещает каждый объект в "$i" прежде, чем выполнить команду эха.

Править: см. комментарии - Вам не нужен "TR" вообще... двоеточия и запятые могут быть убраны включением их в переменной IFS как так:

OIFS="$IFS"; IFS=":,       "; while read p r; do 
 for i in $r; do echo "$p.$i"; done; done <file.txt; IFS="$OIFS"

все сделанные в оболочке - никакие вызовы к внешним программам... (если эхо не встроено). Обратите внимание, что IFS = выше имеет пространство и символ вкладки. Также обратите внимание, что $r во втором для цикла не имеет кавычек вокруг этого - это является преднамеренным, таким образом, оболочка разделит его на пробеле.

2
27.01.2020, 20:13
  • 1
    Вы могли tr ':,' ' ' | tr -s ' '... –  vonbrand 30.03.2013, 16:27
  • 2
    да - вероятно, был бы более дешевым, чем sed, но Вам не нужен второй TR - команда чтения оболочки будет рассматривать последовательности пробела как единственный разделитель..., и это просто заставило меня думать - нам не нужен "TR" вообще! Вот решение для сценария совершенно Оболочки Bourne: OIFS="$IFS"; IFS=":, "; while read p r; do for i in $r; do echo "$p.$i"; done; done; IFS="$OIFS" никогда не должны оставлять оболочку... yay! –  Murray Jensen 01.04.2013, 06:05

Теги

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