Reputation: 16766
I'm trying to write a bash-function to return a specific line of piped output by its number. Currently the full command looks like this:
mdfind 'my_search_string' | sed "2q;d"
That would return the 2nd line of output from the mdfind-command.
I'm trying to turn sed "$1q;d"
into a function that gets assigned as an alias.
How can I process the piped input?
Upvotes: 4
Views: 6917
Reputation: 212664
You just need to protect the variable name:
To define a function named search:
search() { ... | sed -n "${1}p;q"; }
but note that this is not portable sed
. It would be better to do
search() { ... | sed -n "${1}{p; q;}"; }
Indeed, the original sed is not just non-portable, but does not do what you want! It should always quit after processing line 1. If you have a sed
that behaves as you describe in the question statement, you might want to double check!
Upvotes: 2
Reputation: 75618
To return the second line of output, do this:
... | sed -ne 2p
And to use it as a function:
function print_2nd_line {
sed -ne 2p
}
mdfind 'my_search_string' | print_2nd_line
You could also choose shorter names like p2
at your option.
The function can also be customized to be capable of printing second line from specified files like:
function print_2nd_line {
sed -ne 2p -- "$@"
}
print_2nd_line file
... | print_2nd_line ## Still could be used like this.
By the way the more efficient version would be
sed -ne '2{p;q}'
UPDATE
As suggested by Charles Duffy, you could also use this format for POSIX compatibility. Actually it's also compatible with all shells based from the original System V sh.
print_2nd_line() {
sed -ne '2{p;q}' -- "$@"
}
Also, if you want to pass a custom line number to your function, you could have:
print_2nd_line() {
N=$1; shift
sed -ne "${N}{p;q}" -- "$@"
}
Where you can run it as:
... | print_2nd_line 2 ## Still could be used like this.
Or
print_2nd_line 2 file
Upvotes: 7
Reputation: 295954
As an exercise -- this version is in pure bash, not using any external tools at all:
return_line() {
local lineno=$1
while (( lineno > 1 )); do read; (( lineno-- )); done
read -r && printf '%s\n' "$REPLY"
}
# ...to test...
return_line 3 <<<$'one\ntwo\nthree\nfour'
# ...and yes, this works with pipelines...
printf 'one\ntwo\nthree\nfour' | return_line 3
The pure-bash version will typically be faster with short input streams (or when picking an early line from a long stream), but slower with long ones.
Upvotes: 0
Reputation: 6270
My awked bash alias:
alias second="awk 'FNR==2'"
cat file | second
or
second file
So, I don't understand properly, do you want to write a function which gets number of line to filter as parameter? And also you want to process piped input in it to filter out that line? Your piped input will be arguments for your function and you could get all of them by $@
.
I'm sorry, I understand what the OP wanted :)
As I got it, he wants processing std
input by shell function with parameters, i.e.
cmd | func args
So the following works:
function sift { awk "FNR==$1" ;}
Example:
cat file | sift 2
(See comment about awk
vs sed
)
Upvotes: 0