1 |
Florian Philipp writes: |
2 |
|
3 |
> I'm currently streamlining some of my shell scripts to avoid unnecessary |
4 |
> process calls where bash itself is powerful enough. |
5 |
> |
6 |
> At the moment, I want to replace stuff like this: |
7 |
> string='foo:bar:foo' |
8 |
> second_field=$(echo $string | cut -d : -f 2) # should read "bar" |
9 |
> |
10 |
> My current solution is using two string operations: |
11 |
> string='foo:bar:foo' |
12 |
> # remove everything up to and including first ':' |
13 |
> second_and_following=${string#*:} |
14 |
> # remove everything from the first ':' following |
15 |
> second_field=${second_and_following%%:*} |
16 |
|
17 |
That's how I do these things, too. |
18 |
|
19 |
> Of course, I normally do this in a single line with a subshell but it |
20 |
|
21 |
Hmm, I don't get this. Subshell? |
22 |
|
23 |
> still looks cumbersome. Is there a way to do it in a single operation |
24 |
> without a temporary variable? The following does not work: |
25 |
> string='foo:bar:foo' |
26 |
> second_field=${string#:%%:*} |
27 |
|
28 |
I don't think so. But you can write a shell function for this: |
29 |
|
30 |
getfield() |
31 |
{ |
32 |
local str=${1#*:} |
33 |
echo "${str%%:*} |
34 |
} |
35 |
|
36 |
string='foo:bar:foo' |
37 |
second_field=$( getfield "$string" ) |
38 |
|
39 |
But if you need to do this very often in a loop, sometimes going back to |
40 |
cut can speed things up, when you place it outside: |
41 |
|
42 |
See |
43 |
|
44 |
for string in $( < inputfile ) |
45 |
do |
46 |
second_field=$( getfield "$string" ) |
47 |
do_something_with $second_field |
48 |
done |
49 |
|
50 |
vs. |
51 |
|
52 |
secondfields=( $( cut -d : -f 2 inputfile ) ) |
53 |
for secondfield in ${secondfields[@]} |
54 |
do |
55 |
do_something_with $second_field |
56 |
done |
57 |
|
58 |
So, in th e2nd example, cut is called only once, but processes all input |
59 |
lines. The result is put into an array. |
60 |
|
61 |
Of course, all stuff should be put into double quotes in case there is |
62 |
whitescape involved. Setting IFS to $'\n' may be necessary for this when |
63 |
creating the array. |
64 |
|
65 |
Wonko |