从2个文本文件中提取不同的行并附加到新文件

时间:2016-12-14 16:12:06

标签: shell powershell

我有2个文本文件,其中一个名为Invoice1.txt,另一个名为Invoice2.txt。两个文件的格式相同。

Invoice1.txt包含:

  

H~30011000~更多数据......

     

L~13332~更多数据......

     

L~13332~更多数据......

和Invoice2.txt包含:

  

H~30011000~更多数据......

     

L~13332~更多数据......

     

L~13332~更多数据......

     

H~30022000~更多数据......

     

L~13999~更多数据......

     

L~13999~更多数据......

基本上我要做的是创建一个新文件,其中包含来自两个文件的非重复行数据,如下所述。 Invoice2.txt中的最后3行不在Invoice1.txt中,因此将附加到新文件中。

我想要的输出是:

  

H~30022000~更多数据......

     

L~13999~更多数据......

     

L~13999~更多数据......

我如何用Powershell编写它。对于两个.txt文件,我是否必须get-content并选择不相等的对象?

$file1 = "C:\Invoice1.txt"
$file2 = "C:\Invoice2.txt"
$results = "C:\NonDuplicate.txt"

4 个答案:

答案 0 :(得分:3)

编辑适应OP预赛

$file1 = ".\Invoice1.txt"
$file2 = ".\Invoice2.txt"
$results = ".\NonDuplicate.txt"
$Content = Get-Content $File1 
Get-Content $File2 |
  ForEach { if ($Content -notcontains $_) {$_} }|
    Set-Content $Results

这是另一个更容易的步骤:

Get-Content $File2 | Where {$Content -notcontains $_}| Set-Content $Results

输出

> cat .\NonDuplicate.txt
    H~30022000 ~More Data...
    L~13999 ~More Data...
    L~13999 ~More Data...

答案 1 :(得分:2)

有多种方法可以实现它。但我为你做了一个简单的,并在每一行解释了事情的运作方式。

以下是供您参考的脚本和屏幕截图。

   #ifndef NODE_H
#define NODE_H
#include <iostream>
#include <string>
using namespace std;

//an object of type node holds 3 things
// - an item (of type t)
// - a left subtree
// - a right subtree

template<typename T>
class Node {
public:
    Node(T item); //constructor to create a leaf node
    Node(T item, Node *lft, Node *rht); //constructor which creates an internal node 
    ~Node(); //Destructor

    //public data member functions:
    bool searchTree(T key);
    void printTree();

private:
    //private data member functions:
    Node* left;
    Node* right;
    T item;
};

//constructor 
template<typename T>
Node<T>::Node(T i, Node<T> *lft, Node<T> *rht) {
    item = i;
    left = NULL;
    right = NULL;
}

//constructor 
template <typename T>
Node<T>::Node(T i) { //should i be a parameter here?
    item = i; //is this right for this constructor?
}

//destructor
template <typename T>
Node<T>::~Node() {
    delete left;
    delete right;
    //delete;
}


//print tree method
template <typename T>
void Node<T>::printTree() {
    if (left != NULL) {
        left->printTree();
        cout << item << endl;//alphabetical order
    }

    if (right != NULL) {
        right->printTree();
        //cout << item << endl; //post order
    }
}

//search Tree method
template <typename T>
bool Node<T>::searchTree(T key) {
    bool found = false;
    if (item == key) {
        return true;
    }
    if (left != NULL) {
        found = left->searchTree(key);
        if (found) return true;
    }
    if (right != NULL) {
        return right->searchTree(key);
    }
    return false; //if left and right are both null & key is not the search item, then not found == not in the tree.
}

#endif

图片:

Invoice 1

Invoice 2

Non-Duplicates

希望它有所帮助...

答案 2 :(得分:1)

其他提案,无论您有多少个文件都可以使用

$dirwithfile="C:\temp\test"

#extract list of files
$listfile=gci "$dirwithfile\Invoice*.txt" -file

#for every file, get content and extract only rows which not exist in other content file, write result into file NonDuplicate.txt
$listfile |  
    %{ $filename=$_.Name;  gc $_ | where {$row=$_; ($listfile | where Name -ne $filename | gc) -notcontains $row   } } |
        out-file "$dirwithfile\NonDuplicate.txt" -Append

答案 3 :(得分:1)

如果文件很小,那么Compare-Object -ReferenceObject (Get-Content $file1) -DifferenceObject (Get-Content $file2) -PassThru | Set-Content $results 就可以了。

-PassThru

这将为您提供您通过次要编码所要求的结果。它似乎有空白行的问题,所以你可能需要根据你想要的结果发布其中的一些。 Compare-Object就在那里,因此避免了Compare-Object -ReferenceObject (Get-Content $file1) -DifferenceObject (Get-Content $file2) -PassThru | Where-Object{![string]::IsNullOrWhiteSpace($_)} 通常所做的自定义对象。相反,不匹配的行被推送。您可以对文件内容使用临时变量,但如果您只打算使用一次,为什么还要烦恼呢。

$_SERVER['SERVER_NAME'] = preg_replace( array('/^[a-zA-Z]+\:\/\//e'), '', $this->get_Env( array('SERVER_NAME', 'HTTP_HOST') ) );

如果您的文件较大,那么这可能效率不高。