2012-06-05 2 views
1

Я хотел бы разделить var дважды с awk, это то, что я получил до сих пор.awk split var дважды

awk -v p=1,3,8,25-27,4-16 '{split(p,t,",");for (i in t) if(t[i] ~ /-/) split(t[i],t1,"-") {print "-dFirstPage=" t1[1] ,"-dFirstPage=" t1[2]} ELSE {print "-dFirstPage=" t[i] ,"-dFirstPage=" t[i]}}' >outfile 

выход должен быть

-dFirstPage=1 -dLastPage=1 
-dFirstPage=3 -dLastPage=3 
-dFirstPage=8 -dLastPage=8 
-dFirstPage=25 -dLastPage=27 
-dFirstPage=4 -dLastPage=16 

ответ

1

Не могли бы вы передать значение p как вход в AWK ? В этом случае, я хотел бы сделать это следующим образом:

$ echo 1,3,8,25-27,4-16 | awk -F- -v RS=, '{printf "-dFirstPage=%s -dLastPage=%s\n", $1, $2?$2:$1}' 
-dFirstPage=1 -dLastPage=1 
-dFirstPage=3 -dLastPage=3 
-dFirstPage=8 -dLastPage=8 
-dFirstPage=25 -dLastPage=27 
-dFirstPage=4 -dLastPage=16 

Как это работает:

  • я определяю, что запятая будет в разделитель (-v RS=,) и дефис будет разделитель полей (-F-). Таким образом, входной

    1,3,8,25-27,4-16 
    

    будет примерно эквивалентна

    1 
    3 
    8 
    25 27 
    4 16 
    
  • Затем я использую printf:

    '{printf "-dFirstPage=%s -dLastPage=%s\n", $1, $2?$2:$1}' 
    

    Первым параметром является первый столбец. Во втором параметре я спрашиваю, существует ли второй столбец $2; если это так, то значение параметра $2; если нет, значение является первым столбцом $1.

+0

Отлично и просто! – sdf

1

Вы где очень близко (но я не уверен, что это решение будет действительно соответствовать вашим требованиям конечных).

awk -v p=1,3,8,25-27,4-16 ' 
END{ 
     split(p,t,","); 
    for (i in t) { 
    if(t[i] ~ /-/) { 
     split(t[i],t1,"-"); 
     print "-dFirstPage=" t1[1] ,"-dFirstPage=" t1[2] 
    } 
    else { 
     print "-dFirstPage=" t[i] ,"-dFirstPage=" t[i] 
    } 
    } 
}' /dev/null > outfile 

После доработки для окон и более общее решение

echo "1,3,8,25-27,4-16" \ 
| awk ' 
{ 
    split($0,t,","); 
    for (i in t) { 
    if(t[i] ~ /-/) { 
     split(t[i],t1,"-"); 
     print "-dFirstPage=" t1[1] ,"-dFirstPage=" t1[2] 
    } 
    else { 
     print "-dFirstPage=" t[i] ,"-dFirstPage=" t[i] 
    } 
    } 
}' > outfile 

Вы можете изменить свой вопрос, если это требует уточнения.

Надеюсь, это поможет.

+0

По какой-то причине сценарий находится в замкнутом цикле. Я использую gawk на окнах и должен заставить скрипт выйти. Когда скрипт завершился принудительно, результат корректен. Любое предложение? – sdf

+0

Ack !, Windows не имеет printf. См. Пересмотренную версию ;-). Удачи. – shellter

+0

Используете ли вы UNIX-подобную среду в Windows, такую ​​как cygwin или Mingw (или другие), или cmd.exe из окон, чтобы выполнить это? Удачи. – shellter

1

В bash:

#!/bin/bash 

vars=1,3,8,25-27,4-16 

for pages in `echo $vars | tr ',' '\n'`; do 
    if [[ -n $(echo $pages | grep --only-matching "-") ]]; then 
     firstPage=`echo ${pages%%-*}` 
     lastPage=`echo ${pages##*-}` 
    else 
     firstPage=$pages 
     lastPage=$pages 
    fi 
    echo "-dFirstPage=${firstPage} -dLastPage=${lastPage}" 
done 

Выходные:

-dFirstPage=1 -dLastPage=1 
-dFirstPage=3 -dLastPage=3 
-dFirstPage=8 -dLastPage=8 
-dFirstPage=25 -dLastPage=27 
-dFirstPage=4 -dLastPage=16 

Применить советы некоторых @ shellter в:

#!/bin/bash 

vars=1,3,8,25-27,4-16 
for pages in `echo $vars | tr ',' '\n'`; do 
    case $pages in 
     *-*) 
      firstPage=${pages%%-*} 
      lastPage=${pages##*-} 
      ;; 
     *) 
      firstPage=$pages 
      lastPage=$pages 
      ;; 
    esac 
    echo "-dFirstPage=${firstPage} -dLastPage=${lastPage}" 
done 
+0

приятное альтернативное решение! Хорошее использование $ {pages %% - *}. Но почему люди боятся случаев дела? Вы можете исключить все дополнительные процессы с 'case $ pages в * - *) .... ;; *) firstPage = $ pages; lastPage = $ pages ;; esac'. Кроме того, я не думаю, что вам нужно «backtic echo», просто «firstPage = $ {pages %% - *}; ​​...« Удачи всем ». – shellter

+0

Спасибо за обзор, @shellter. –

+0

' while IFS =, read -r pages, do ... done <(echo "$ vars") '(другими словами, это неправильное использование' for'). Нет необходимости в '[[-n $ (echo | grep)]] '- вы можете сделать' if echo | grep -qs' (или перенаправить stdout и stderr на '/ dev/null') напрямую без скобок. Кроме того, что сказал shellter. –

1

Вы были очень близко:

awk -v p=1,3,8,25-27,4-16 'BEGIN {split(p,t,",");for (i in t) if(t[i] ~ /-/) {split(t[i],t1,"-"); print "-dFirstPage=" t1[1] ,"-dFirstPage=" t1[2]} else {print "-dFirstPage=" t[i] ,"-dFirstPage=" t[i]}}' >outfile 
  • Используйте BEGIN пункт
  • Изменить "ELSE" в else
  • Перемещение фигурную скобку из перед первым print до split и pla ce точка с запятой, где она была
+0

Спасибо, что работает отлично. – sdf

Смежные вопросы