LINUX.ORG.RU

Переставить строки местами


0

2

Интересует как в bash можно переставить строки местами : парные на место непарных. Например: было 1 2 3 4 должно быть 2 1 4 3 Парные у меня - исполнитель, непарные - композиция. Спасибо.


>парные на место непарных. Например: было 1 2 3 4 должно быть 2 1 4 3

Это называется четные/нечетные?

Dimanc ★★
()
Ответ на: комментарий от Dimanc

> cat TEST|perl -e 'while(<>){if($i%2==0){$f=$_;}else{print; print $f;}; $i++;} if ($i%2==1) {print $f;}'

многабукаф %)

cat TEST | perl -ne '@t&&(print$_,pop@t)||(@t=$_)'

arsi ★★★★★
()
Ответ на: комментарий от Dimanc

> Оно последнюю нечетную строчку не печатает.

конечно. ведь автору это и не требуется.

arsi ★★★★★
()
Ответ на: комментарий от arsi

можно и покороче, и пояснее, а то этот «рор» запутывает — думаешь, что там целый массив, а там только одно значение

cat TEST | perl -ne '$a=$a?(print($_,$a),""):$_'

кроме того, в обоих реализациях баг — если строка состоит допустим из одного нуля «0»

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> в обоих реализациях баг — если строка состоит допустим из одного нуля «0»

нет, баг только в вашей ;) @t в скалярном контексте даст количество элементов, даже если там только один элемент и он эквивалентен false (т.е. равет undef, пустой строке или 0).

вашу реализацию необходимо исправить следующим образом:

cat TEST | perl -ne '$a=defined$a?(print($_,$a),undef):$_'
arsi ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> че-то я у себя тоже этот баг не вижу

действительно. предпоследняя строка не может содержать только «0» и не содержать «\n», а «0\n» != false.

arsi ★★★★★
()
Ответ на: комментарий от arsi

выходит, что

cat TEST | perl -ne '$a=$a?(print($_,$a),""):$_'

работает не хуже

___________________________

Тут, кстати, надо сделать лирическое отступление против динамической типизации. Не сказав статически, числа у нас или строки в переменной, имеем необходимость дублировать операторы (= eq != ne и т.д.) и сложное поведение в случае «0»?«foo»:«bar». Программа удлиняется, т.к. по-хорошему в нее *должен* быть включен комментарий, что " '0' не может быть предпоследней строкой ".

www_linux_org_ru ★★★★★
()

Если именно на bash, то также как и где-нибудь в си:

replace_string_pairs_in_line () {
  odd=0
  prev_string=""
  result=""
  for string in ${1} ; do
    if [ "${odd}" == "0" ] ; then
      prev_string="${string}"
      odd=1
    else
      result="${result} ${string} ${prev_string}"
      odd=0
    fi
  done
  echo "${result}"
}

replace_string_pairs_in_file () {
  while read line  
  do
    echo `replace_string_pairs_in_line "${line}"`
  done < ${1}
}
$ replace_string_pairs_in_line "1 :a 2 :b"
 :a 1 :b 2
$ cat test
1 :a 2 :b
3 :c 4 :d
5 :e 6 :f
$ replace_string_pairs_in_file test
:a 1 :b 2
:c 3 :d 4
:e 5 :f 6

С другой стороны:

junk_dsl_forever () {
  while read a b c d
  do
    echo "${b} ${a} ${d} ${c}"
  done < ${1}
}

Тот же эффект:

$ junk_dsl_forever test
:a 1 :b 2
:c 3 :d 4
:e 5 :f 6
quasimoto ★★★★
()
Ответ на: комментарий от www_linux_org_ru

> '0' не может быть предпоследней строкой

ну дык. «0» ни при каких условиях не может быть предпоследней строкой, т.к. предпоследняя строка будет минимум «0\n» (после $_ = <>), которая в булевом контексте будет true.

зы: вы слишком всё усложняете. перл намного проще ;)

arsi ★★★★★
()

cat list | while read n1; read n2; do echo $n2; echo $n1; done

anonymous
()
Ответ на: комментарий от arsi

> зы: вы слишком всё усложняете. перл намного проще ;)

ахренеть как просто

«0» это false, но «0.0», «+0», "-0", «00» и «0\n» все true

в нормальном языке, я считаю, должно быть так:

$a=$a?(print($_,$a),undef):$_

здесь происходит вывод типов: т.к. $a явно может принимать значение undef, то тип у нее Maybe<String>; соответственно false может быть только в том случае, когда она undef

сложнее сказать, что будет в случае

/usr/bin/language -ne '$a=$a?(print($_,$a),""):$_'

я думаю, тут в первой итерации тип (и значение) $a это undef, а в последующих итерациях это String, так что дальше опять false будет только в случае «»

хотя, может, в таком случае надо бить по рукам, и заставлять писать полностью

/usr/bin/language -e '$a=«»' -ne '$a=$a?(print($_,$a),""):$_'

www_linux_org_ru ★★★★★
()

sed -n '$p;h;n;p;x;p'

anonymous
()
Ответ на: комментарий от www_linux_org_ru

> «0» это false, но «0.0», «+0», "-0", «00» и «0\n» все true

да, потому что результатом арифметических операций, из этого набора, может быть только «0». и это часто используется в булевом контексте («while ($count--) { ... }», например).

я думаю, тут в первой итерации тип (и значение) $a это undef

тип — SCALAR, значение — undef.

а в последующих итерациях это String, так что дальше опять false будет только в случае «»

и в последующих итерациях это будет SCALAR. судьба у неё такая, SCALAR-ом быть, как и у всех переменных с сигилом «$». и да, числа — это тоже SCALAR-ы, и ссылки на другие объекты — тоже. но числовой скаляр (результат арифметических операций) может принимать только «0» из false-ов, строка в чистом виде (определена и не равна числу) — только «» (ей, кстати, равно значение фэйла булевых выражений), другие скаляры — только undef.

… -e '$a=«»' -ne '$a=$a?(print($_,$a),""):$_'

… -ne 'BEGIN{$a=«»} $a=$a ne""?(print($_,$a),""):$_'

тогда уж ;)

arsi ★★★★★
()
Ответ на: комментарий от Dimanc

>Тот же баг.

Бага нет. кол-во строк всегда четное по исходному условию.

anonymous
()

ещё варианты на перле принимаются? ;)

cat TEST | perl -pe 'print scalar<>'

или даже

cat TEST | perl -pe 'print"".<>'

arsi ★★★★★
()
Ответ на: комментарий от Dimanc

> Я серьезно. Как работает этот код?

я тоже серьёзно ;)

man perlrun

читайте внимательно) если не поймёте до завтра — утром объясню во всех подробностях. но т.к. объяснять я не люблю, искренне надеюсь на ваше понимание ;)

arsi ★★★★★
()
Ответ на: комментарий от arsi

>man perlrun

Все понял. :) Не знал про этот мануал, а по 'perl --help' не понял, что аргумент -p делает :)

Dimanc ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.