1

I have *.dat files like below in a directory:

$ cat holiday_us.dat
20210101 1     New Year's Day
20210102 2     Labor Day
20210103 1     Independence Day

Output I want:

20210101_New Year'sDay
20210102_LaborDay
20210103_IndependenceDay

Code I tried:

for file in /home/path/holly*.dat
do 
awk -f ' ' '{print $1,"_",print$2}' "$file"
done
}

I am getting below output:

20210101
New
20210102
Labor
20210103
Independence
3
  • 3
    outputs on line1 and line3 conflict each other as well as violate the roles. so what should be the output? all spaces removed? or based on what condition you kept in first line partially but not in second and third lines? – αғsнιη Feb 28 at 5:35
  • 2
    Your command line awk -f ' ' '{print $1,"_",print$2}' "$file" can't be correct. -f specifies the file that contains the awk program; in you case, the name of this file consists of a space. Which can be OK, but the string after it looks like an awk program, but contains a syntax error. – berndbausch Feb 28 at 10:37
  • That sample input holiday_us.dat looks like it's tab-separated, is it? – Ed Morton Mar 1 at 0:34
7

Change the output field separator OFS to a null (empty) string and change $2 to _:

$ awk -v OFS= '{ $2="_" }1' *.dat
20210101_NewYear'sDay
20210102_LaborDay
20210103_IndependenceDay
1

This should do it.

for file in /home/path/*.tmp ; do cat $file |  awk '{print$1,"_",$3$4$5}' | sed 's/ //g' ; done
1
cat data | awk '{print $1"_"$3$4$5}'

This will output what your looking for hope it helps any questions feel free to ask.

Or you can do this way.

awk '{print $1"_"$3$4$5}' data.dat

for file in /path/to/file/holly*.dat; do awk '{print $1"_"$3$4$5}' $file; done

0

Also with awk but supposing the output you want is

20210101_New Year's Day
20210102_Labor Day
20210103_Independence Day

Set regexp for FS: one space followed by one digit followed by one or more spaces.


awk -v FS=' [[:digit:]] +' -v OFS='_' '{print $1,$NF}' file
20210101_New Year's Day
20210102_Labor Day
20210103_Independence Day

or using sub() function with the same regexp:

awk 'sub(/ [[:digit:]] +/,"_") 1' file
20210101_New Year's Day
20210102_Labor Day
20210103_Independence Day
0
awk '{$2="";print $1"_"$(NF-2),$(NF-1)$NF }' p.txt| awk '{gsub(/_[ ]*/,"_",$0);print }'

output

20210101_New Year'sDay
20210102_LaborDay
20210103_IndependenceDay

Python

#!/usr/bin/python

    import re
    k=re.compile(r'_\s+')
    m=open('filename','r')
    for i in m:
        z=i.strip().split(' ')
        d="{0}_{1} {2}{3}".format(z[0],z[-3],z[-2],z[-1])
        print re.sub(k,"_",d)

output

20210101_New Year'sDay
20210102_LaborDay
20210103_IndependenceDay
0

This awk statement uses the C-style printf statements. The additional benefit here is you have more flexibility in formatting the output. Here NF is the number of fields in the current line and is set by awk.

awk -F ' ' '{printf("%s_", $1); for (i=3; i<=NF;i++) printf("%s ", $i); print ""}' $file

Sample Output:

20210101_New Year's Day
20210102_Labor Day
20210103_Independence Day

In fact, since space is the default delimiter, you can also use this:

awk '{printf("%s_", $1); for (i=3; i<=NF;i++) printf("%s ", $i); print ""}' $file

0

If you can rely on the column widths,

awk '{print $1"_"$3}' FIELDWIDTHS="8 7 *" /home/path/holly*.dat

If that's a tab character before the last column you could adjust the counts or use it this way:

awk '{print substr($1,1,8)"_"$2}' FS=$'\t' /home/path/holly*.dat

and another way:

awk '{print substr($1,1,8}"_"$2' FS='[\t ]{2,}' /home/path/holly*.dat

or even

awk '{print $1"_"$2}' FS=' [0-9]  +' /home/path/holly*.dat

Not the answer you're looking for? Browse other questions tagged or ask your own question.