https://ezsnote.tistory.com/entry/cat-으로-읽은-여러줄-멀티라인-xargs-로-각각-넘기기
를 통해서 output 리스트를 한줄한줄씩 읽어서 function 대입 (...뭔가의 처리)를 하게 해놓은뒤 평화로운 나날을 보내는중... 갑자기 이상한 현상이 나왔다.
갑자기 파싱된 element 값을 function 대입하고 있던것이다. ... 앵? 난 줄을 읽어와서 그걸 function 처리하려고 했던건데?
확인해보니.. 새롭게 값이 추가되면서 그 값중에 공백이 들어가는 부분이 있었는데 xargs 가 그 공백을 새로운 줄로 처리하고 있었다;
즉
1_2_3_4 를 한줄로 읽어서 넘기고 있었는데 ( '_' 는 구분자.. delim)
1_2_3_4_5 1 .. 처럼 뒤에 '5 1' 이 추가되면서
1_2_3_4_5 까지만 읽고 1을 다음 데이타.. 즉 다음줄로 처리하려고 했던것이다.
찾아보면 다양항 스킬을 난무해가며 이걸 처리하는 방법들이 있다. xargs 의 옵션질 및 뭐... print 로 명령줄을 만들어서 그걸 실행하게 할 수도 있고 등등등...
근데... 이 간단한 처리.. 를 위한 간단한 해결방법을 쓰기로 했다. sed 를 써서 공백을 "" empty 로 치환하는거지.
$> 원하는 필터링중... | sed 's/ //g' | xargs 원하는 function
sed 로 준 s 와 g 에 대해서 예전에 스크립트좀 공부했다면 무슨의미인지 알것이다. 즉 시작과 끝까지.. 이다.해서
'처음/공백을/empty로/끝까지' 라고 생각하면된다.
해서 넘겨받은 한 줄에 대해서 빈 스페이스를 모두 "" empty 형태로 바꾸고 output 으로 내놓게 된다. 이걸 다시 뭔가를 처리할 function (이게 뭐.. 스크립트가 될 수도 있고 파이썬이 될수도 있고 등등 ) 에게 넘겨주는 것이다.
!!!!
https://stackoverflow.com/questions/23142776/xargs-split-at-newlines-not-spaces
xargs 에서도 간단히 할 수 있다. -d 주면 모두 넘긴다. 다만 -d 는 GNU 확장에서나 먹히는 명령이므로 -0(숫자) 으로 하면 된다.
here is my problem in short
$ echo 'for i in $@; do echo arg: $i; done; echo DONE' > /tmp/test.sh
$ echo "ac\nbc\ncc\n" | xargs bash /tmp/test.sh
arg: ac
arg: bc
arg: cc
DONE
Which is what i expect, but
$ echo "ac s\nbc s\ncc s\n" | xargs -d \n bash /tmp/test.sh
arg: ac
arg: s
arg: bc
arg: s
arg: cc
arg: s
DONE
Shouldn't the output be?
arg: ac s
arg: bc s
arg: cc s
DONE
How do I get the 2nd output with xargs?
Try:
printf %b 'ac s\nbc s\ncc s\n' | xargs -d '\n' bash /tmp/test.sh
You neglected to quote the \n
passed to -d
, which means that just n
rather than \n
was passed to xargs
as the delimiter - the shell "ate" the \
(when the shell parses an unquoted string, \
functions as an escape character; if an ordinary character follows the \
- n
in this case - only that ordinary character is used).
Also heed @glenn jackman's advice to double-quote the $@
inside the script (or omit the in "$@"
part altogether).
Also: xargs -d
is a GNU extension, which, for instance, won't work on FreeBSD/macOS. To make it work there, see @glenn jackman's xargs -0
-based solution.
Note that I'm using printf
rather than echo
to ensure that the \n
instances in the string are interpreted as newlines in all Bourne-like shells:
In bash
and ksh
[1], echo
defaults to NOT interpreting \
-based escape sequences (you have to use -e
to achieve that) - unlike in zsh
and strictly POSIX-compliant shells such as dash
.
Therefore, printf
is the more portable choice.
[1] According to the manual, ksh
's echo
builtin exhibits the same behavior as the host platform's external echo
utility; while this may vary across platforms, the Linux and BSD/macOS implementations do not interpret \
escape sequences by default.
Your shell script needs to use "$@"
not $@
See http://www.gnu.org/software/bash/manual/bashref.html#Special-Parameters
I see in the xargs manual on my machine:
xargs reads items from the standard input, delimited by blanks [...] or newlines
(emphasis mine)
Thus:
$ echo $'ac s\nbc s\ncc s\n' | xargs bash /tmp/test.sh
arg: ac
arg: s
arg: bc
arg: s
arg: cc
arg: s
DONE
$ printf "%s\0" "ac s" "bc s" "cc s" | xargs -0 bash /tmp/test.sh
arg: ac s
arg: bc s
arg: cc s
DONE
With the former, you get the equivalent of
bash /tmp/test.sh ac s bc s cc s
versus using null-separator
bash /tmp/test.sh "ac s" "bc s" "cc s"
You need to be clear about what the delimiter is with xargs when the data contains whitespace.
$ printf "%s\n" "ac s" "bc s" "cc s" | xargs -d $'\n' bash /tmp/test.sh
arg: ac s
arg: bc s
arg: cc s
DONE
$ echo $'ac s\nbc s\ncc s\n' | xargs -d $'\n' bash /tmp/test.sh
arg: ac s
arg: bc s
arg: cc s
arg:
DONE
Note the extra arg in the last case, echo
already adds a newline, so you don't need an extra one unless you use echo -n
'IT > Unix&Linux' 카테고리의 다른 글
zsh oh my zsh ! plugin docker, k8s and auto complete... 자동완성 (0) | 2019.12.28 |
---|---|
cat 으로 읽은 여러줄 멀티라인 xargs 로 각각 넘기기 (0) | 2018.11.20 |
curl... wget 대치가능 --> httpie 로 대체중 (0) | 2015.06.22 |
우분투 리눅스 데스크탑 설치후 런레벨 변경 runlevel (0) | 2015.05.27 |
albert ... like alfred (0) | 2015.05.25 |
\n
passed to-d
. – mklement0 Apr 17 '14 at 20:47printf
-\0
-xargs -0
solution is a nice alternative, because it is more portable (will work on OSX too, for instance, wherexargs -d
is not available). – mklement0 Apr 17 '14 at 21:01