I have a control file - cntl.txt
2
3
5
Data file - data.txt
red
blue
yellow
green
violet
orange
I need to reading the lines matching from control file, here the output expected is:
blue
yellow
violet
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityExample of a very inefficient solution:
for i in $(<control.txt); do awk -v c=$i 'NR~c{ print $0 }' data.txt; done;
I report also a good solution I learned tonight:
awk 'FNR==NR{ z[$0]++;next }; FNR in z' control.txt data.txt
awk
solution is certainly worth an upvote imho (especially since the OP tagged awk
)
Nov 2, 2016 at 23:14
Using only POSIX specified features of Sed:
sed -n -e "$(sed '/./s/$/p/' cntl.txt)" data.txt
Of course if your cntl.txt
file has lines besides numbers, you may get an error. But if it has empty lines these will be handled correctly (i.e. they will not affect the output).
Try this:
join <(nl data.txt|sort -k1b,1) <(cat cntl.txt|sort -k1b,1) | sort -nk1,1 | cut -d' ' -f2-
nl - will enumerate lines for you
1 red
2 blue
3 yellow
4 green
5 violet
6 orange
| sort -k1b,1 - will sort them by the line number (first field), lexicographically
cat cntl.txt| sort -k1b,1 - will sort the control file in the same order
2
3
5
join <() <() - will join the sorted (and numbered) "data" with the sorted "control", on the first field (i.e. line number)
2 blue
3 yellow
5 violet
|sort -nk1,1 - will re-sort the results numerically (to put the lines back in order)
| cut -d' ' -f2- - will drop the line number field
blue
yellow
violet
With sed
only:
sed -n "$(sed -e 's/$/p;/' < cntl.txt)" data.txt
tr
. Newlines are a perfectly acceptable command separator for Sed. (Also, $(...)
is the preferred syntax for command substitution.)
Another possible solution:
IFS=$'\n' read -d '' -r -a colors < 'data.txt'; unset IFS;
for i in $(<cntl.txt); do
echo ${colors[i-1]}
done
IFS line sets up internal file separator as newline and inserts each line from data.txt into array. After that you loop through lines in cntl.txt and print array elements with given index from it (minus 1 because you start your data.txt from 1, not from 0, otherwise it would be unnecessary).