tcsh alias com cmds complexos, citações e argumentos cmd

1

Eu estou amarrando um alias de um conjunto de comandos pipe, passei por alguns dos threads aqui e descobri que a linha cmd deve ser usada de forma diferente. em vez de $ 1 use!: 1 mas parece não funcionar para mim no contexto abaixo

Este é o meu conjunto de cmds que estou querendo usar como alias (sua mediana de cálculo)

shell>  cat file_with_numbers| awk '{print $1}' | sort -n | awk ' { a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'
shell> 1.15

Eu quero alias a parte abaixo como "mediana"

sort -n | awk ' { a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'

para que eu possa usar apenas

shell> cat file_with_numbers| awk '{print $1}' | median

alias median 'sort -n | awk ' { a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }''

Mal colocado (). // aspas simples com erro

alias median "sort -n | awk ' { a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'"

cat file| awk '{print $5}'|  median
awk:  { a[i++]=; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }
awk:           ^ syntax error

então mudei para \!:1 & tentei o seguinte e ainda não funcionou. como posso ter esse alias corretamente?

1 > tentativa 1

alias median "sort -n | awk ' { a[i++]=\!:1; } END { x=int ( ( i+1 ) /2 ) ; if ( x < ( i+1 ) /2 ) print ( a[x-1]+a[x] ) /2 ; else print a[x-1] ; }' "


cat file|  awk '{print $5}' | median
Bad ! arg selector.

2 > trial 2

alias median "sort -n | awk ' { a[i++]=\!:1; } END { x=int ( ( i+1 ) /2 ) ; if ( x < ( i+1 ) /2 ) print ( a[x-1]+a[x] ) /2 ; else print a[x-1] ; }' "

cat file| awk '{print $5}' | median
awk:  { a[i++]=!:1; } END { x=int ( ( i+1 ) /2 ) ; if ( x < ( i+1 ) /2 ) print ( a[x-1]+a[x] ) /2 ; else print a[x-1] ; }
awk:            ^ syntax error

trial 3 >

    
por dan 28.08.2018 / 16:21

3 respostas

1

A menos que você se preocupe em reinventar a roda, você também pode usar o GNU datamash :

alias median 'datamash median 1'

datamash espera colunas delimitadas por tabulações, embora você possa alterar o delimitador com -t .

Para o seu problema em particular, note que $parameter expansão em (t) csh é feita entre aspas duplas, mas ao contrário de shells parecidos com Bourne, não pode ser desativado com barras invertidas, então você precisa de algo como:

alias median "sort -n | awk '{a[NR]="\$"1}; END {x = int(NR/2); print NR % 2 ? a[x+1] : (a[x]+a[x+1])/2}'"

Isso é sair das aspas duplas para inserir o $ as \$ ou seguir a abordagem de Mark e usar aspas simples, mas sair delas para inserir aspas simples literais.

    
por 28.08.2018 / 17:14
1

Você pode colocar uma sequência de comandos de linha única em um alias, mas pode ser necessário adicionar barras invertidas e aspas simples ou duplas aqui e ali. Mas, a menos que você precise chamar o alias com parâmetros ou elementos do histórico do shell ou precisar maximizar a velocidade, às vezes é mais fácil colocar a sequência de comandos como está em um arquivo, marcá-la como executável e colocá-la em algum lugar em seu arquivo. caminho de pesquisa ( $PATH ou $path ).

Mas para transformar o seguinte em um alias:

sort -n | awk '{ a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'

Você precisa se certificar de que

  • o operador de pipeline está dentro de uma string entre aspas; caso contrário, terminará o comando alias
  • o $ está dentro de uma cadeia delimitada por aspas simples ou está fora de qualquer cadeia entre aspas e é precedida por \ (obrigado, Stéphane, pela alternativa)
  • não há cotações únicas aninhadas

Não use \!:1 para tentar produzir $1 . \!:1 seria usado se você passasse um parâmetro para seu alias. Você só quer que o literal $1 seja visto pelo awk.

A coisa mais segura a fazer nesse caso é incluir o máximo possível do alias com aspas simples e usar " apenas para colocar uma aspa simples literal. Você verá duas ocorrências de "'" abaixo.

ubuntu% alias median 'sort -n | awk '"'"'{ a[i++]=$1 ; } END { x=int ( ( i+1 ) /2 ) ; if ( x < ( i+1 ) /2 ) print ( a[x-1]+a[x] ) /2 ; else print a[x-1] ; }'"'"

ubuntu% seq 1 9 | median
5
    
por 28.08.2018 / 18:39
0

Tente isto:

$ alias median="sort -n|awk ' { a[i++]="\"; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'"

$ cat file_with_numbers| awk '{print $1}'|median
    
por 28.08.2018 / 16:51