Print everything before nth delimiter
I’m looking for a sed
solution like the one here: Print everything after nth delimiter
sed -E 's/^([^]*[]){3}//' infile
but to extract the text before nth delimiter, instead of nth delimiter like the example. Something that works with all sed variants. And operate on all lines like the example.
The delimiter in this example is but could be for any other. Should work with any version of sed.
Why don’t you use cut
?
cut -d '' -f 1-3 infile
With sed
, instead of deleting the match, capture it and use a back-reference to replace the whole line with the captured group:
sed -E 's/(^([^]*[]){3}).*/1/' infile
Though that would also print the trailing backslash… To avoid that you could run
sed -E 's/(^([^]*[]){2}[^]*).*/1/' infile
Using awk
:
$ awk -v var=3 'BEGIN{FS=OFS="\"}
(NF>=var){ split($0,arr,OFS);
$0="";
for (i=1; i<=var; ++i) $(NF+1)=arr[i];
print}'
To keep nth delimiter the following command may be used.
$ awk -v var=3 'BEGIN{FS=OFS="\"}
(NF>=var){ for (i=1; i<=var; ++i) printf "%s%s", $i, OFS; print ""}'
$ nawk '(match($0, /^([^\]*[\]){3}/))
{ print substr($0,RSTART,RLENGTH)}'
With GNU awk
:
The following command uses back-referencing a captured group. This is an awk command taken from this answer. Thanks to @don_crissti
$ awk -F "\" -v col=3 '(NF>=col){print gensub(/(^([^\]*[\]){3}).*/, "\1", "g")}'
You could replace the nth delimiter with newline (which cannot otherwise occur in the pattern space) and then delete everything starting with that newline. Here for n == 3:
sed 's/delim/
/3; P; d'
Or if the nth delimiter must be retained in the output:
sed 's/delim/&
/3; P; d'
To skip the lines that don’t have n delimiters:
sed -n 's/delim/
/3; t1
d; :1
P'
a shorter awk:
awk NF=3 FS='\' OFS='\'
- define input and output field separators
- set number of fields to keep