Awk - split only on first appearance

I have a line like:

one:two:three:four:five:six seven:eight 

and I want to use awk to get $1 equal to one, and $2 - two:three:four:five:six seven:eight

I know I can get it by doing sed earlier. That is, to change the first occurrence : with sed , then awk , using the new delimiter.

However, replacing the separator with a new one would not help me, since I cannot guarantee that the new separator will no longer be somewhere in the text.

I want to know if there is an opportunity to get awk to behave this way

So something like:

 awk -F: '{print $1,$2}' 

will print:

 one two:three:four:five:six seven:eight 

I also want to do some manipulations on $1 and $2 , so I don't want to just replace the first occurrence :

+7
bash awk
source share
3 answers

Without any substitutions

 echo "one:two:three:four:five" | awk -F: '{ st = index($0,":");print $1 " " substr($0,st+1)}' 

The index command finds the first occurrence of ":" in the entire line, so in this case the variable st will be set to 4. Then I use the substr function to grab the rest of the line from the beginning from position st + 1 if the ending number is not specified, it will jump to the end of the line. Exit

 one two:three:four:five 

If you want to continue processing, you can always set a string for a variable for further processing.

 rem = substr($0,st+1) 

Please note that this was tested on Solaris AWK, but I see no reason why this should not work for other tastes.

+11
source share

Closest you can contact GNU awk FPAT :

 $ awk '{print $1}' FPAT='(^[^:]+)|(:.*)' file one $ awk '{print $2}' FPAT='(^[^:]+)|(:.*)' file :two:three:four:five:six seven:eight 

But $2 will include the main delimiter, but you can use substr to fix this:

 $ awk '{print substr($2,2)}' FPAT='(^[^:]+)|(:.*)' file two:three:four:five:six seven:eight 

So, all together:

 $ awk '{print $1, substr($2,2)}' FPAT='(^[^:]+)|(:.*)' file one two:three:four:five:six seven:eight 

Saving substr results back to $2 will allow us to continue processing on $2 without the main delimiter:

 $ awk '{$2=substr($2,2); print $1,$2}' FPAT='(^[^:]+)|(:.*)' file one two:three:four:five:six seven:eight 

Solution that should work with mawk 1.3.3 :

 awk '{n=index($0,":");s=$0;$1=substr(s,1,n-1);$2=substr(s,n+1);print $1}' FS='\0' one awk '{n=index($0,":");s=$0;$1=substr(s,1,n-1);$2=substr(s,n+1);print $2}' FS='\0' two:three:four five:six:seven awk '{n=index($0,":");s=$0;$1=substr(s,1,n-1);$2=substr(s,n+1);print $1,$2}' FS='\0' one two:three:four five:six:seven 
+2
source share

Some like this?

 echo "one:two:three:four:five:six" | awk '{sub(/:/," ")}1' one two:three:four:five:six 

This replaces the first : with a space. Then you can get it at $ 1, $ 2

 echo "one:two:three:four:five:six" | awk '{sub(/:/," ")}1' | awk '{print $1,$2}' one two:three:four:five:six 

Or in the same awk, so even with a replacement, you get $ 1 and $ 2 the way you like

 echo "one:two:three:four:five:six" | awk '{sub(/:/," ");$1=$1;print $1,$2}' one two:three:four:five:six 

EDIT: Using another separator, you can get the first one as a registered $1 and rest at $2 as follows:

 echo "one:two:three:four:five:six seven:eight" | awk -F\| '{sub(/:/,"|");$1=$1;print "$1="$1 "\n$2="$2}' $1=one $2=two:three:four:five:six seven:eight 

Unique delimiter

 echo "one:two:three:four:five:six seven:eight" | awk -F"#;#." '{sub(/:/,"#;#.");$1=$1;print "$1="$1 "\n$2="$2}' $1=one $2=two:three:four:five:six seven:eight 
+1
source share

All Articles