0

I have a file called test.out with the below lines in:

-rw-rw----    1 informix informix    9117025 Jan 21 05:22 shop4_0_Log0000331875.Z
-rw-rw----    1 informix informix    8897981 Jan 21 05:24 shop4_0_Log0000331876.Z
-rw-rw----    1 informix informix    9325351 Jan 21 05:31 shop4_0_Log0000331877.Z
-rw-rw----    1 informix informix    9645109 Jan 21 05:34 shop4_0_Log0000331878.Z
-rw-rw----    1 informix informix    9950581 Jan 21 05:40 shop4_0_Log0000331879.Z
-rw-rw----    1 informix informix   10655940 Jan 21 05:59 shop4_0_Log0000331880.Z
-rw-rw----    1 informix informix   10832325 Jan 21 06:39 shop4_0_Log0000331881.Z
-rw-rw----    1 informix informix    8521443 Jan 21 07:42 shop4_0_Log0000331882.Z
-rw-rw----    1 informix informix   10283566 Jan 21 08:02 shop4_0_Log0000331883.Z
-rw-rw----    1 informix informix   10633957 Jan 21 08:51 shop4_0_Log0000331884.Z

I want to print all lines above grep value 331881 parameter:

My desired outcome must be like below:

-rw-rw----    1 informix informix    9117025 Jan 21 05:22 shop4_0_Log0000331875.Z
-rw-rw----    1 informix informix    8897981 Jan 21 05:24 shop4_0_Log0000331876.Z
-rw-rw----    1 informix informix    9325351 Jan 21 05:31 shop4_0_Log0000331877.Z
-rw-rw----    1 informix informix    9645109 Jan 21 05:34 shop4_0_Log0000331878.Z
-rw-rw----    1 informix informix    9950581 Jan 21 05:40 shop4_0_Log0000331879.Z
-rw-rw----    1 informix informix   10655940 Jan 21 05:59 shop4_0_Log0000331880.Z

Using the command below command I can specify how much lines above to print:

grep -n 331881 test.out | cut -d':' -f1 |  xargs  -n1 -I % awk "NR<=%+0 && NR>=%-1" test.out | sed '$d'

The above command will only print the specified amount of lines in this case 1 line, but I want to change the above to print all above the grepped line. I am struggling to find a solution to my problem or an easier way.

AdminBee
  • 22,803

5 Answers5

2

Assuming that you are located in the directory that holds the listed files, using zsh:

ls -ld shop4_0_Log<331882->.Z

The <331882-> is a zsh-specific glob that matches integers that are 331882 or larger.

With some other shell:

for name in shop4_0_Log*.Z; do
    number=${name#shop4_0_Log}
    number=${number%.Z}

    if [ "$number" -ge 331882 ]; then
        ls -ld "$name"
    fi
done

Here, we loop over the names that start with shop4_0_Log and end with .Z. For each such name, we pick out the integer part of the filename, and if it is 331882 or more we call ls -ld on the name.

If the leading zeros are causing the shell to interpret some of the numbers as octal (it doesn't in my tests), then use 10#$number in the test to force the number to be interpreted as a decimal integer (this is supported by ksh and bash and some other shells).

Neither of these two variations relies on the presence of a text file that contains some ls output.

Related:

Kusalananda
  • 333,661
1

I think you can just use awk directly:

awk '/331881/ { exit } 1' test.out

This will print all lines, but for a line matching 331881, quit.

muru
  • 72,889
1

Another good tool would be sed:

sed -n '/shop4_0_Log0000331881\.Z$/q;p' test.out
Torin
  • 1,703
0

Try removing the and condition, remove the following code from your one liner:

&& NR>=%-1
NixMan
  • 123
0
j=`awk '/331881/{print NR}' file`

awk -v j="$j" '{a[++i]=$0}/331881/{for(x=NR-j;x<NR;x++)print a[x]}' file

output

-rw-rw----    1 informix informix    9117025 Jan 21 05:22 shop4_0_Log0000331875.Z
-rw-rw----    1 informix informix    8897981 Jan 21 05:24 shop4_0_Log0000331876.Z
-rw-rw----    1 informix informix    9325351 Jan 21 05:31 shop4_0_Log0000331877.Z
-rw-rw----    1 informix informix    9645109 Jan 21 05:34 shop4_0_Log0000331878.Z
-rw-rw----    1 informix informix    9950581 Jan 21 05:40 shop4_0_Log0000331879.Z
-rw-rw----    1 informix informix   10655940 Jan 21 05:59 shop4_0_Log0000331880.Z