I have files with hundreds of lines of varying length. I want to find each line with the string "New" and print the first 7 characters and the 10th from the last character.

For example, cat file1.txt

1234567 New line with irrelevant info x end line
2345678 irrelevant line
3456789 New line with different irrelevant info y end line
4567890 irrelevant line
5678901 New line with yet more irrelevant info z end line

And my output would be:

1234567 x 
3456789 y
5678901 z
  • 1
    Expected output seems wrong .... second line starting with 2345678 is irrelevant. – George Vasiliou Dec 1 '18 at 21:36
  • 1
    ... as is the third. – RudiC Dec 1 '18 at 21:45


Assuming the lines contain at least 10 characters (if not, the behaviour is unspecified for the second substr(), you can add a && length >= 10 or && length >= 17 after /New/ to skip the lines that have fewer than 10 or 17 characters):

awk '/New/ {print substr($0, 1, 7), substr($0, length - 9, 1)}'

or assuming the lines contain at least 17 characters (the lines that don't will be skipped):

sed -n '/New/ s/^\(.\{7\}\).*\(.\).\{9\}$/\1 \2/p'
  • 1
    What is the difference with the answer of RomanPerekhrest ? Your awk solution is identical and your sed solution is also identical, it just uses basic regex instead of extended regex.... – George Vasiliou Dec 1 '18 at 21:53
  • @GeorgeVasiliou, he edited the awk solution in after I had started writing mine and I hadn't seen his edit before I posted mine. His sed one is GNU specific, my intention was to offer a standard solution. – Stéphane Chazelas Dec 1 '18 at 21:56
  • ok then. Fair answer. Has happened also to me. If i had more time my answer would also be like Roman's answer, but this guy was fast! :-) – George Vasiliou Dec 1 '18 at 22:00

Choose one you like:

awk solution:

awk '/New/{ print substr($0, 1, 7), substr($0, length-9, 1) }' file1.txt

sed solution:

sed -rn '/New/ s/^(.{7}).*(.).{9}$/\1 \2/p' file1.txt

Sample output (for both approaches):

1234567 x
3456789 y
5678901 z

This is one "brutal" gawk solution that does the job, using null as field separator FS and output field separator OFS , meaning each char of inputfile is considered to be a field for awk.

awk '/New/{print $1,$2,$3,$4,$5,$6,$7," ",$(NF-9)}' FS="" OFS="" file1
1234567 x
3456789 y
5678901 z

More solutions with grep / sed will follow.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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