Answers.Body: <p>Here's one way using <a href="/questions/tagged/awk" class="post-tag" title="show questions tagged &#39;awk&#39;" aria-label="show questions tagged &#39;awk&#39;" rel="tag" aria-labelledby="tag-awk-tooltip-container">awk</a>. This avoids the creation of the intermediary files by matching the alphabetic characters in the fourth column. If the prefix has not been seen, it is added to an array along with a counter, which is only incremented when the prefix has not yet been seen. We then store the seq ids and the replacement strings in another array. Once we've finished reading the first file, we can then query the first column of the second file in the arguments list. If the seq id in the first column exists in the array of seq ids, we can print the replacement string and remaining columns.</p>
  <p>With the following in a file called <code>script.awk</code>:</p>
  <pre><code>BEGIN {
  
     counter = 1
  }
  
  FNR==NR {
      if( match(<span class="math-container">$4, /^NZ_[A-Z]+/) ) {
          prefix = substr($</span>4, RSTART, RLENGTH)
  
          if( !(prefix in seen) ) {
              seen[prefix] = counter++
          }
  
          seq_ids[$3] = &quot;seq&quot; seen[prefix]
      }
  
      next
  }
  
  $1 in seq_ids {
  
      print seq_ids[<span class="math-container">$1], $</span>2, <span class="math-container">$3, $</span>4
  }
  </code></pre>
  <p>Run using:</p>
  <pre><code>awk -f script.awk file1 file2
  </code></pre>
  <p>Results:</p>
  <pre><code>seq1 19301 20914 fill_color=green_a0
  seq1 16726 18337 fill_color=green_a0
  seq1 167934 169650 fill_color=green_a0
  seq2 200621 202367 fill_color=red_a0
  seq2 160164 161903 fill_color=green_a0
  seq2 31356 33104 fill_color=green_a0
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-15T19:01:29.717Z
Answers.Text: thank you very much,
Answers.UserDisplayName: Umar
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-15T15:58:01.937Z
Answers.LastActivityDate: 2023-03-15T15:58:01.937Z
Answers.UserDisplayName: Steve
Body: <p>I have multiple sets of files, so I grepped the list from a column in a separate file such as <code>file1.txt</code>. I want to change all other files by using this <code>file1.txt</code> based on a matching string.</p>
  <p>For example, I am pasting three files here</p>
  <p><strong>File 1:</strong></p>
  <pre><code>chr - seq1 NZ_JAHWGH010000010.1 0 60562 green_a4
  chr - seq3 NZ_JAHWGH010000012.1 0 466573 green_a4
  chr - seq5 NZ_JAHWGH010000013.1 0 125526 green_a4
  chr - seq39 NZ_CAJGBF010000006.1 0 211154 green_a4
  chr - seq40 NZ_CAJGBF010000007.1 0 199119 green_a4
  chr - seq41 NZ_CAJGBF010000008.1 0 190934 green_a4
  chr - seq42 NZ_CAJGBF010000009.1 0 178251 green_a4
  </code></pre>
  <p>I extracted the required information using grep; the command is given below:</p>
  <pre><code>grep &quot;NZ_JAHWGH&quot; file.txt |awk '{print <span class="math-container">$3}' &gt;file1.txt
  grep "NZ_CAJGBF" file.txt |awk '{print $</span>3}' &gt;file2.txt
  </code></pre>
  <p>Now I wanted to use these <code>file1.txt</code> and <code>file2.txt</code> to change another file. Output will be like if list in <code>file1.txt</code> matches then all matched lists should be substituted as seq1 similarly using the second <code>file2.txt</code>. I want to substitute all matching patterns as seq2.</p>
  <p>For example the file is given here to be changed by using information from the previous file:</p>
  <pre><code>seq3 19301 20914 fill_color=green_a0
  seq1 16726 18337 fill_color=green_a0
  seq5 167934 169650 fill_color=green_a0
  seq42 200621 202367 fill_color=red_a0
  seq41 160164 161903 fill_color=green_a0
  seq40 31356 33104 fill_color=green_a0
  </code></pre>
  <p>And final output after the change should be as follows:</p>
  <pre><code>seq1 19301 20914 fill_color=green_a0
  seq1 16726 18337 fill_color=green_a0
  seq1 167934 169650 fill_color=green_a0
  seq2 200621 202367 fill_color=red_a0
  seq2 160164 161903 fill_color=green_a0
  seq2 31356 33104 fill_color=green_a0
  </code></pre>
  <p>I tried using this command:</p>
  <pre><code>for i in f2.txt; do
      grep -wf f1.txt <span class="math-container">$i |
      awk '{$1="seq1";print}'
      grep -wf other.txt $</span>i |
      awk '{$1=&quot;seq2&quot;;print}'
  done
  </code></pre>
  <p>2nd attempt:</p>
  <pre><code>grep -wf f1.txt f2.txt |
  sed -e 's/seq[0-9]*/seq1/g'
  </code></pre>
  <p>Is this correct? If it is correct is there any more efficient way to do it? Also it is only printing to the console. I want the output and also changes in the main file. Kindly improve my scripts.</p>
  <p>I appreciate yout time and help.</p>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-03-13T08:34:48.417Z
Comments.Text: So if I understand this correctly you have a file with multiple seqs and depending on a column value for example ""NZ_JAHWGH" you want to rename the `seqx` term with seq1, seq2, seq3 etc, depending on the column value. In the end all seqx values associated with NZ_y will be seq1, NZ_z will be seq_2 etc.. Is that right? It might be helpful to specify the context somewhat
Comments.UserDisplayName: Macintosh
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-03-14T15:01:04.723Z
Comments.Text: ya its like that, First I want to rename first file, and later same changes with other files also, but main information is only provided in first file such as information of sequence, so similar changes should also needed in other file since every file will be used for analysis in one go. Thanks for ypur comment
Comments.UserDisplayName: Umar
Tags: <linux><awk><shell><for-loop><sed>
Title: Replace a string in a column of a text file based on matching string listed in another file using Linux
ThreadText: # Replace a string in a column of a text file based on matching string listed in another file using Linux
  
  (Asked by: username_0 on 2023-03-12)
  
  I have multiple sets of files, so I grepped the list from a column in a separate file such as `file1.txt`. I want to change all other files by using this `file1.txt` based on a matching string.
  
  For example, I am pasting three files here
  
  **File 1:**
  
  ```
  chr - seq1 NZ_JAHWGH010000010.1 0 60562 green_a4
  chr - seq3 NZ_JAHWGH010000012.1 0 466573 green_a4
  chr - seq5 NZ_JAHWGH010000013.1 0 125526 green_a4
  chr - seq39 NZ_CAJGBF010000006.1 0 211154 green_a4
  chr - seq40 NZ_CAJGBF010000007.1 0 199119 green_a4
  chr - seq41 NZ_CAJGBF010000008.1 0 190934 green_a4
  chr - seq42 NZ_CAJGBF010000009.1 0 178251 green_a4
  
  ```
  
  I extracted the required information using grep; the command is given below:
  
  ```
  grep "NZ_JAHWGH" file.txt |awk '{print $3}' >file1.txt
  grep "NZ_CAJGBF" file.txt |awk '{print $3}' >file2.txt
  
  ```
  
  Now I wanted to use these `file1.txt` and `file2.txt` to change another file. Output will be like if list in `file1.txt` matches then all matched lists should be substituted as seq1 similarly using the second `file2.txt`. I want to substitute all matching patterns as seq2.
  
  For example the file is given here to be changed by using information from the previous file:
  
  ```
  seq3 19301 20914 fill_color=green_a0
  seq1 16726 18337 fill_color=green_a0
  seq5 167934 169650 fill_color=green_a0
  seq42 200621 202367 fill_color=red_a0
  seq41 160164 161903 fill_color=green_a0
  seq40 31356 33104 fill_color=green_a0
  
  ```
  
  And final output after the change should be as follows:
  
  ```
  seq1 19301 20914 fill_color=green_a0
  seq1 16726 18337 fill_color=green_a0
  seq1 167934 169650 fill_color=green_a0
  seq2 200621 202367 fill_color=red_a0
  seq2 160164 161903 fill_color=green_a0
  seq2 31356 33104 fill_color=green_a0
  
  ```
  
  I tried using this command:
  
  ```
  for i in f2.txt; do
      grep -wf f1.txt $i |
      awk '{$1="seq1";print}'
      grep -wf other.txt $i |
      awk '{$1="seq2";print}'
  done
  
  ```
  
  2nd attempt:
  
  ```
  grep -wf f1.txt f2.txt |
  sed -e 's/seq[0-9]*/seq1/g'
  
  ```
  
  Is this correct? If it is correct is there any more efficient way to do it? Also it is only printing to the console. I want the output and also changes in the main file. Kindly improve my scripts.
  
  I appreciate yout time and help.
  
  **Tags:** linux, awk, shell, for-loop, sed
  
  > **Comments:**
  > **username_1**: So if I understand this correctly you have a file with multiple seqs and depending on a column value for example ""NZ_JAHWGH" you want to rename the `seqx` term with seq1, seq2, seq3 etc, depending on the column value. In the end all seqx values associated with NZ_y will be seq1, NZ_z will be seq_2 etc.. Is that right? It might be helpful to specify the context somewhat  
  > **username_0**: ya its like that, First I want to rename first file, and later same changes with other files also, but main information is only provided in first file such as information of sequence, so similar changes should also needed in other file since every file will be used for analysis in one go. Thanks for ypur comment  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_2 on 2023-03-15. Score: 1 | Accepted answer
  
  Here's one way using [awk](/questions/tagged/awk "show questions tagged 'awk'"). This avoids the creation of the intermediary files by matching the alphabetic characters in the fourth column. If the prefix has not been seen, it is added to an array along with a counter, which is only incremented when the prefix has not yet been seen. We then store the seq ids and the replacement strings in another array. Once we've finished reading the first file, we can then query the first column of the second file in the arguments list. If the seq id in the first column exists in the array of seq ids, we can print the replacement string and remaining columns.
  
  With the following in a file called `script.awk`:
  
  ```
  BEGIN {
  
     counter = 1
  }
  
  FNR==NR {
      if( match($4, /^NZ_[A-Z]+/) ) {
          prefix = substr($4, RSTART, RLENGTH)
  
          if( !(prefix in seen) ) {
              seen[prefix] = counter++
          }
  
          seq_ids[$3] = "seq" seen[prefix]
      }
  
      next
  }
  
  $1 in seq_ids {
  
      print seq_ids[$1], $2, $3, $4
  }
  
  ```
  
  Run using:
  
  ```
  awk -f script.awk file1 file2
  
  ```
  
  Results:
  
  ```
  seq1 19301 20914 fill_color=green_a0
  seq1 16726 18337 fill_color=green_a0
  seq1 167934 169650 fill_color=green_a0
  seq2 200621 202367 fill_color=red_a0
  seq2 160164 161903 fill_color=green_a0
  seq2 31356 33104 fill_color=green_a0
  
  ```
  
  > **Comments:**
  > **username_0**: thank you very much,  
  
  ---
  
  