Reputation: 49
Text file looks like this:
key11=val1|key12=val2|key13=val3
key21=val1|key22=val2|key23=val3
How can I extract keys so that:
key11|key12|key13
key21|key22|key23
I have tried unsuccessfully :
awk '{ gsub(/[^[|]=]+=/,"") }1' file.txt
gives back the actual data:
key11=val1|key12=val2|key13=val3
key21=val1|key22=val2|key23=val3
Upvotes: 2
Views: 204
Reputation: 1517
awk -F'[=|]' '{print $1,$3,$5}' OFS="|" file
key11|key12|key13
key21|key22|key23
Upvotes: 1
Reputation: 519
I did this with sed
:
sed -r 's/([[:alnum:]]*)=[[:alnum:]]*/\1/g' < file.txt
tested here and got:
key11|key12|key13
key21|key22|key23
s/<pattern>/<subst>/
means "replace <pattern>
by <subst>
", and with the g
in the end it will do it for every pattern found in the line.
The [[:alnum:]]*
is equivalent to [0-9a-zA-Z]*
, and means any number of letters or digits.
The first pattern between parentesis will correspond to \1
in the substitution, the second \2
and so on.
So, it will match every "key=value" and replace it by "key".
Upvotes: 1
Reputation: 246992
Since you tagged bash
while IFS='=|' read -ra words; do
n=${#words[@]}
for ((i=1; i<n; i+=2)); do
unset words[i]
done
( IFS='|'; echo "${words[*]}" )
done < file
Upvotes: 2
Reputation: 37298
Here's one solution
echo "key11=val1|key12=val2|key13=val3" \
| awk -F'[=|]' '{
for (i=1;i<=NF;i+=2){
printf("%s%s", $i, (i<(NF-1))?"|":"")
}
print""
}'
output
key11|key12|key13
It should also work by passing in the filename as an argument to awk
, i.e.
awk -F'[=|]' '{for (i=1;i<=NF;i+=2){printf("%s%s", $i, (i<(NF-1))?"|":"") }print""}' file1 [file_more_as_will_fit]
Discussion
We use a multiple character value for FS (FieldSeperator) so each =
and |
char mark the beginning of a new field.
-F'[=|]'
Because we know we want to start with field1 for output and skip every other field, we use
for (i=1;i<=NF;i+=2)
printf
formats the output as defined by the format string '%s%s'
. There area a zillion options available for printf
format strs, but you only need the value for $i
(the looping value that generates the key) and whether to print a |
char or not.
printf("%s%s", $i ...)
And we use awk
's ternary operator, which evaluates what element number is being processed (i<..)
. As long as it is not the 2nd to last field, the |
char is emitted.
(i<(NF-1))?"|":""
IHTH
Upvotes: 1
Reputation: 195159
This can be done by awk
, by setting FS
and OFS
:
kent$ awk -F'=[^|]*' -v OFS="" '$1=$1' file
key11|key12|key13
key21|key22|key23
or safer: awk -F.... '{$1=$1}1' file
kent$ sed 's/=[^|]*//g' file
key11|key12|key13
key21|key22|key23
Upvotes: 1